doc/
2003-09-14 Marcus Brinkmann <marcus@g10code.de> * gpgme.texi (Multi Threading): Correct documentation on memory synchronization requirement. tests/ 2003-09-14 Marcus Brinkmann <marcus@g10code.de> * gpg/t-thread1.c (main): Call init_gpgme here. (initialize_gpgme): Function removed.
This commit is contained in:
parent
0a952a59b6
commit
b4473cfffd
@ -1,5 +1,8 @@
|
||||
2003-09-14 Marcus Brinkmann <marcus@g10code.de>
|
||||
|
||||
* gpgme.texi (Multi Threading): Correct documentation on memory
|
||||
synchronization requirement.
|
||||
|
||||
* gpgme.texi (Locale): New section.
|
||||
(Multi Threading): Set locale in example.
|
||||
|
||||
|
@ -551,51 +551,17 @@ For example, if you use GNU Pth, the right name is
|
||||
@item
|
||||
The function @code{gpgme_check_version} must be called before any
|
||||
other function in the library, because it initializes the thread
|
||||
support subsystem in @acronym{GPGME}. To achieve this in all
|
||||
generality, it is necessary to synchronize the call to this function
|
||||
with all other calls to functions in the library, using the
|
||||
synchronization mechanisms available in your thread library.
|
||||
Otherwise, specific compiler or CPU memory cache optimizations could
|
||||
lead to the situation where a thread is started and uses
|
||||
@acronym{GPGME} before the effects of the initialization are visible
|
||||
for this thread. It doesn't even suffice to call
|
||||
@code{gpgme_check_version} before creating this other
|
||||
thread@footnote{In SMP systems the new thread could be started on
|
||||
another CPU before the effects of the initialization are seen by that
|
||||
CPU's memory cache. Not doing proper synchronization here leads to
|
||||
the same problems the double-checked locking idiom has. You might
|
||||
find that if you don't do proper synchronization, it still works in
|
||||
most configurations. Don't let this fool you. Someday it might lead
|
||||
to subtle bugs when someone tries it on a DEC Alpha or an SMP
|
||||
machine.}.
|
||||
|
||||
For example, if you are using POSIX threads, each thread that wants to
|
||||
call functions in @acronym{GPGME} could call the following function
|
||||
before any function in the library:
|
||||
|
||||
@example
|
||||
#include <stdlib.h>
|
||||
#include <locale.h>
|
||||
#include <pthread.h>
|
||||
#include <gpgme.h>
|
||||
|
||||
void
|
||||
initialize_gpgme (void)
|
||||
@{
|
||||
static int gpgme_init;
|
||||
static pthread_mutext_t gpgme_init_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
pthread_mutex_lock (&gpgme_init_lock);
|
||||
if (!gpgme_init)
|
||||
@{
|
||||
gpgme_check_version (NULL);
|
||||
gpgme_set_locale (NULL, LC_CTYPE, setlocale (LC_CTYPE, NULL));
|
||||
gpgme_set_locale (NULL, LC_MESSAGES, setlocale (LC_MESSAGES, NULL));
|
||||
gpgme_init = 1;
|
||||
@}
|
||||
pthread_mutex_unlock (&gpgme_init_lock);
|
||||
@}
|
||||
@end example
|
||||
support subsystem in @acronym{GPGME}. To achieve this in
|
||||
multi-threaded programs, you must synchronize the memory with respect
|
||||
to other threads that also want to use @acronym{GPGME}. For this, it
|
||||
is sufficient to call @code{gpgme_check_version} before creating the
|
||||
other threads using @acronym{GPGME}@footnote{At least this is true for
|
||||
POSIX threads, as @code{pthread_create} is a function that
|
||||
synchronizes memory with respects to other threads. There are many
|
||||
functions which have this property, a complete list can be found in
|
||||
POSIX, IEEE Std 1003.1-2003, Base Definitions, Issue 6, in the
|
||||
definition of the term ``Memory Synchronization''. For other thread
|
||||
packages other, more relaxed or more strict rules may apply.}.
|
||||
|
||||
@item
|
||||
Any @code{gpgme_data_t} and @code{gpgme_ctx_t} object must only be
|
||||
|
@ -1,5 +1,8 @@
|
||||
2003-09-14 Marcus Brinkmann <marcus@g10code.de>
|
||||
|
||||
* gpg/t-thread1.c (main): Call init_gpgme here.
|
||||
(initialize_gpgme): Function removed.
|
||||
|
||||
* gpg/t-thread1.c: New file.
|
||||
* gpg/Makefile.am (TESTS): Add t-thread1.c.
|
||||
(t_thread1_LDADD): New variable.
|
||||
|
@ -31,22 +31,6 @@
|
||||
|
||||
#define ROUNDS 20
|
||||
|
||||
|
||||
void
|
||||
initialize_gpgme (void)
|
||||
{
|
||||
static int gpgme_init;
|
||||
static pthread_mutex_t gpgme_init_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
pthread_mutex_lock (&gpgme_init_lock);
|
||||
if (!gpgme_init)
|
||||
{
|
||||
init_gpgme (GPGME_PROTOCOL_OpenPGP);
|
||||
gpgme_init = 1;
|
||||
}
|
||||
pthread_mutex_unlock (&gpgme_init_lock);
|
||||
}
|
||||
|
||||
|
||||
void *
|
||||
thread_one (void *name)
|
||||
@ -156,6 +140,8 @@ main (int argc, char *argv[])
|
||||
pthread_t tone;
|
||||
pthread_t ttwo;
|
||||
|
||||
init_gpgme (GPGME_PROTOCOL_OpenPGP);
|
||||
|
||||
pthread_create (&tone, NULL, thread_one, "A");
|
||||
pthread_create (&ttwo, NULL, thread_two, "A");
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user