Couchbase C Client  3.3.6
Asynchronous C Client for Couchbase
Thread Safety

The library uses no internal locking and is thus not safe to be used concurrently from multiple threads.

As the library contains no globals you may call into the library from multiple threads so long as the same data structure (specifically, the same lcb_INSTANCE *) is not used.

/* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
/*
* Copyright 2017-2020 Couchbase, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <pthread.h>
typedef struct {
lcb_INSTANCE *instance;
pthread_mutex_t mutex;
} my_CTX;
/*
* This function uses the same instance between threads. A lock
* is required for every operation
*/
static void *
thrfunc_locked(void *arg)
{
my_CTX *ctx = arg;
lcb_CMDGET cmd = { 0 };
LCB_CMD_SET_KEY(&cmd, "Hello", strlen("Hello"));
pthread_mutex_lock(&ctx->mutex);
lcb_get3(ctx->instance, NULL, &cmd);
lcb_wait(ctx->instance);
pthread_mutex_unlock(&ctx->mutex);
return NULL;
}
/*
* This function uses an instance per thread. Since no other thread
* is using the instance, locking is not required
*/
static void *
thrfunc_unlocked(void *arg)
{
lcb_INSTANCE *instance;
lcb_create(&instance, NULL);
lcb_connect(instance);
LCB_CMDGET cmd = { 0 };
lcb_get3(instance, NULL, &cmd);
lcb_destroy(instance);
return NULL;
}
int main(void)
{
pthread_t thrs[10];
my_CTX ctx;
int ii;
lcb_create(&ctx.instance, NULL);
lcb_connect(ctx.instance);
lcb_wait(ctx.instance);
pthread_mutex_init(&ctx.mutex, NULL);
for (ii = 0; ii < 10; ii++) {
pthread_create(&thrs[ii], NULL, thrfunc_locked, &ctx);
}
for (ii = 0; ii < 10; ii++) {
void *ign;
pthread_join(thrs[ii], &ign);
}
lcb_destroy(ctx.instance);
pthread_mutex_destroy(&ctx.mutex);
for (ii = 0; ii < 10; ii++) {
pthread_create(&thrs[ii], NULL, thrfunc_unlocked, NULL);
}
for (ii = 0; ii < 10; ii++) {
void *ign;
pthread_join(thrs[ii], &ign);
}
return 0;
}
Main header file for Couchbase.
void lcb_destroy(lcb_INSTANCE *instance)
Destroy (and release all allocated resources) an instance of lcb.
lcb_STATUS lcb_create(lcb_INSTANCE **instance, const lcb_CREATEOPTS *options)
Create an instance of lcb.
struct lcb_st lcb_INSTANCE
Library handle representing a connection to a cluster and its data buckets.
Definition: couchbase.h:35
lcb_STATUS lcb_connect(lcb_INSTANCE *instance)
Schedule the initial connection This function will schedule the initial connection for the handle.
lcb_STATUS lcb_wait(lcb_INSTANCE *instance, lcb_WAITFLAGS flags)
Wait for completion of scheduled operations.
@ LCB_WAIT_DEFAULT
Behave like the old lcb_wait()
Definition: couchbase.h:1854
#define LCB_CMD_SET_KEY(cmd, keybuf, keylen)
Set the key for the command.
Definition: utils.h:52

In this quick mockup example, the same lcb_INSTANCE * is being used from multiple threads and thus requires locking. Now if each thread created its own lcb_INSTANCE * it would be free to operate upon it without locking.