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:
Marcus Brinkmann 2003-09-14 14:48:48 +00:00
parent 0a952a59b6
commit b4473cfffd
4 changed files with 19 additions and 61 deletions

View File

@ -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.

View File

@ -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

View File

@ -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.

View File

@ -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");