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>
|
2003-09-14 Marcus Brinkmann <marcus@g10code.de>
|
||||||
|
|
||||||
|
* gpgme.texi (Multi Threading): Correct documentation on memory
|
||||||
|
synchronization requirement.
|
||||||
|
|
||||||
* gpgme.texi (Locale): New section.
|
* gpgme.texi (Locale): New section.
|
||||||
(Multi Threading): Set locale in example.
|
(Multi Threading): Set locale in example.
|
||||||
|
|
||||||
|
@ -551,51 +551,17 @@ For example, if you use GNU Pth, the right name is
|
|||||||
@item
|
@item
|
||||||
The function @code{gpgme_check_version} must be called before any
|
The function @code{gpgme_check_version} must be called before any
|
||||||
other function in the library, because it initializes the thread
|
other function in the library, because it initializes the thread
|
||||||
support subsystem in @acronym{GPGME}. To achieve this in all
|
support subsystem in @acronym{GPGME}. To achieve this in
|
||||||
generality, it is necessary to synchronize the call to this function
|
multi-threaded programs, you must synchronize the memory with respect
|
||||||
with all other calls to functions in the library, using the
|
to other threads that also want to use @acronym{GPGME}. For this, it
|
||||||
synchronization mechanisms available in your thread library.
|
is sufficient to call @code{gpgme_check_version} before creating the
|
||||||
Otherwise, specific compiler or CPU memory cache optimizations could
|
other threads using @acronym{GPGME}@footnote{At least this is true for
|
||||||
lead to the situation where a thread is started and uses
|
POSIX threads, as @code{pthread_create} is a function that
|
||||||
@acronym{GPGME} before the effects of the initialization are visible
|
synchronizes memory with respects to other threads. There are many
|
||||||
for this thread. It doesn't even suffice to call
|
functions which have this property, a complete list can be found in
|
||||||
@code{gpgme_check_version} before creating this other
|
POSIX, IEEE Std 1003.1-2003, Base Definitions, Issue 6, in the
|
||||||
thread@footnote{In SMP systems the new thread could be started on
|
definition of the term ``Memory Synchronization''. For other thread
|
||||||
another CPU before the effects of the initialization are seen by that
|
packages other, more relaxed or more strict rules may apply.}.
|
||||||
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
|
|
||||||
|
|
||||||
@item
|
@item
|
||||||
Any @code{gpgme_data_t} and @code{gpgme_ctx_t} object must only be
|
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>
|
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/t-thread1.c: New file.
|
||||||
* gpg/Makefile.am (TESTS): Add t-thread1.c.
|
* gpg/Makefile.am (TESTS): Add t-thread1.c.
|
||||||
(t_thread1_LDADD): New variable.
|
(t_thread1_LDADD): New variable.
|
||||||
|
@ -31,22 +31,6 @@
|
|||||||
|
|
||||||
#define ROUNDS 20
|
#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 *
|
void *
|
||||||
thread_one (void *name)
|
thread_one (void *name)
|
||||||
@ -156,6 +140,8 @@ main (int argc, char *argv[])
|
|||||||
pthread_t tone;
|
pthread_t tone;
|
||||||
pthread_t ttwo;
|
pthread_t ttwo;
|
||||||
|
|
||||||
|
init_gpgme (GPGME_PROTOCOL_OpenPGP);
|
||||||
|
|
||||||
pthread_create (&tone, NULL, thread_one, "A");
|
pthread_create (&tone, NULL, thread_one, "A");
|
||||||
pthread_create (&ttwo, NULL, thread_two, "A");
|
pthread_create (&ttwo, NULL, thread_two, "A");
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user