Libcurl - CURLSHOPT_LOCKFUNC - 如何使用它?

Libcurl - CURLSHOPT_LOCKFUNC - how to use it?

请告诉我使用选项 CURLSHOPT_LOCKFUNC ?

的细微差别

我找到了一个例子 here

我不太明白,是否有一个互斥数组用于阻止对数据的访问?

--这是示例中的这部分代码:

static pthread_mutex_t lockarray[NUM_LOCKS];  Is it an array of mutexes ?
//.....
static void lock_cb(CURL *handle, curl_lock_data data,
                    curl_lock_access access, void *userptr)
{
  (void)access;
  (void)userptr;
  (void)handle;
  pthread_mutex_lock(&lockarray[data]);
}

也就是说,从这部分代码-我可以得出结论,不同的互斥量用于锁定 CURLSHOPT_LOCKFUNC ?

我不明白这是怎么回事?同步线程访问数据是否需要多个互斥量?

而且这部分代码也不清楚:

pthread_mutex_lock(&lockarray[data]);

data是什么变量?

文档说:https://curl.se/libcurl/c/CURLSHOPT_LOCKFUNC.html

The data argument tells what kind of data libcurl wants to lock. Make sure that the callback uses a different lock for each kind of data.

什么意思:“libcurl 想要锁定什么样的数据”??

看不懂

是的,代码使用了互斥体数组。

curl_lock_data 是在 curl.h 中定义的 enum 并指定 curl 使用锁的不同类型的数据:

/* Different data locks for a single share */
typedef enum {
  CURL_LOCK_DATA_NONE = 0,
  /*  CURL_LOCK_DATA_SHARE is used internaly to say that
   *  the locking is just made to change the internal state of the share
   *  itself.
   */
  CURL_LOCK_DATA_SHARE, 
  CURL_LOCK_DATA_COOKIE,
  CURL_LOCK_DATA_DNS,
  CURL_LOCK_DATA_SSL_SESSION,
  CURL_LOCK_DATA_CONNECT,
  CURL_LOCK_DATA_LAST
 } curl_lock_data;

由于值是连续的,因此代码将它们用作数组的索引。

因此,例如,当多个线程访问共享 cookie 数据时,它们将 lock/unlock CURL_LOCK_DATA_COOKIE 互斥。

curl_lock_accesscurl.h 中定义的另一个 enum,它指定了获得给定锁的原因:

/* Different lock access types */
typedef enum {
  CURL_LOCK_ACCESS_NONE = 0,   /* unspecified action */
  CURL_LOCK_ACCESS_SHARED = 1, /* for read perhaps */
  CURL_LOCK_ACCESS_SINGLE = 2, /* for write perhaps */
  CURL_LOCK_ACCESS_LAST        /* never use */
} curl_lock_access;

这些原因之间的区别对于互斥体来说并不重要,互斥体只有独占访问的概念,这意味着一次只有一个线程可以持有锁。这就是代码未使用 access 参数的原因。

但是,其他类型的锁,例如 RW (reader/writer) 锁,确实有共享访问(即多个线程可以同时持有锁)与独占访问的概念。当多个线程想要访问相同的共享数据只是为了读取时,它们之间不阻塞是有意义的。只有当一个线程想要修改共享数据时,其他线程才会被阻止访问该数据,以读取或写入,直到修改完成。

例如:

const int NUM_LOCKS = CURL_LOCK_DATA_LAST + 1;
static pthread_rwlock_t lockarray[NUM_LOCKS];

...

static void lock_cb(CURL *handle, curl_lock_data data,
                    curl_lock_access access, void *userptr)
{
  (void)handle;
  (void)userptr;
  switch (access) {
    case CURL_LOCK_ACCESS_SHARED:
      pthread_rwlock_rdlock(&lockarray[data]);
      break;
    case CURL_LOCK_ACCESS_ SINGLE:
      pthread_rwlock_wrlock(&lockarray[data]);
      break;
  }
}

static void unlock_cb(CURL *handle, curl_lock_data data,
                    curl_lock_access access, void *userptr)
{
  (void)handle;
  (void)access;
  (void)userptr;
  pthread_rwlock_unlock(&lockarray[data]);
}