/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% TTTTT H H RRRR EEEEE AAA DDDD %
% T H H R R E A A D D %
% T HHHHH RRRR EEE AAAAA D D %
% T H H R R E A A D D %
% T H H R R EEEEE A A DDDD %
% %
% %
% MagickCore Thread Methods %
% %
% Software Design %
% Cristy %
% March 2003 %
% %
% %
% Copyright 1999-2019 ImageMagick Studio LLC, a non-profit organization %
% dedicated to making software imaging solutions freely available. %
% %
% You may not use this file except in compliance with the License. You may %
% obtain a copy of the License at %
% %
% https://imagemagick.org/script/license.php %
% %
% 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 declarations.
*/
#include "MagickCore/studio.h"
#include "MagickCore/memory_.h"
#include "MagickCore/thread_.h"
#include "MagickCore/thread-private.h"
/*
Typedef declarations.
*/
typedef struct _MagickThreadValue
{
size_t
number_threads;
void
**values,
(*destructor)(void *);
} MagickThreadValue;
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% C r e a t e M a g i c k T h r e a d K e y %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% CreateMagickThreadKey() creates a thread-specific data key visible to all
% threads in the process.
%
% The format of the CreateMagickThreadKey method is:
%
% MagickThreadKey CreateMagickThreadKey(MagickThreadKey *key)
%
% A description of each parameter follows:
%
% o key: opaque objects used to locate thread-specific data.
%
% o destructor: associate an optional destructor with each key value.
%
*/
MagickExport MagickBooleanType CreateMagickThreadKey(MagickThreadKey *key,
void (*destructor)(void *))
{
#if defined(MAGICKCORE_THREAD_SUPPORT)
return(pthread_key_create(key,destructor) == 0 ? MagickTrue : MagickFalse);
#elif defined(MAGICKCORE_WINDOWS_SUPPORT)
magick_unreferenced(destructor);
*key=TlsAlloc();
return(*key != TLS_OUT_OF_INDEXES ? MagickTrue : MagickFalse);
#else
{
MagickThreadValue
**keys;
keys=(MagickThreadValue **) key;
*keys=(MagickThreadValue *) AcquireQuantumMemory(1,sizeof(**keys));
if (*keys != (MagickThreadValue *) NULL)
{
(*keys)->number_threads=GetOpenMPMaximumThreads();
(*keys)->values=AcquireQuantumMemory((*keys)->number_threads,
sizeof(void *));
if ((*keys)->values == (void *) NULL)
*keys=RelinquishMagickMemory(*keys);
else
(void) memset((*keys)->values,0,(*keys)->number_threads*
sizeof(void *));
(*keys)->destructor=destructor;
}
return((*keys != (MagickThreadValue *) NULL) ? MagickTrue : MagickFalse);
}
#endif
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% D e l e t e M a g i c k T h r e a d K e y %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% DeleteMagickThreadKey() deletes a thread-specific data key.
%
% The format of the DeleteMagickThreadKey method is:
%
% MagickBooleanType DeleteMagickThreadKey(MagickThreadKey key)
%
% A description of each parameter follows:
%
% o key: the thread key.
%
*/
MagickExport MagickBooleanType DeleteMagickThreadKey(MagickThreadKey key)
{
#if defined(MAGICKCORE_THREAD_SUPPORT)
return(pthread_key_delete(key) == 0 ? MagickTrue : MagickFalse);
#elif defined(MAGICKCORE_WINDOWS_SUPPORT)
return(TlsFree(key) != 0 ? MagickTrue : MagickFalse);
#else
{
MagickThreadValue
*keys;
register ssize_t
i;
keys=(MagickThreadValue *) key;
for (i=0; i < (ssize_t) keys->number_threads; i++)
if ((keys->destructor != (void *) NULL) &&
(keys->values[i] != (void *) NULL))
{
keys->destructor(keys->values[i]);
keys->values[i]=(void *) NULL;
}
keys=(MagickThreadValue *) RelinquishMagickMemory(keys);
}
return(MagickTrue);
#endif
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% G e t M a g i c k T h r e a d V a l u e %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% GetMagickThreadValue() returns the value currently bound to the specified
% key on behalf of the calling thread.
%
% The format of the GetMagickThreadValue method is:
%
% void *GetMagickThreadValue(MagickThreadKey key)
%
% A description of each parameter follows:
%
% o key: the thread key.
%
*/
MagickExport void *GetMagickThreadValue(MagickThreadKey key)
{
#if defined(MAGICKCORE_THREAD_SUPPORT)
return(pthread_getspecific(key));
#elif defined(MAGICKCORE_WINDOWS_SUPPORT)
return(TlsGetValue(key));
#else
{
MagickThreadValue
*keys;
keys=(MagickThreadValue *) key;
return(keys->values[GetOpenMPThreadId()]);
}
#endif
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% S e t M a g i c k T h r e a d V a l u e %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% SetMagickThreadValue() binds a value to the specified key on behalf of the
% calling thread.
%
% The format of the SetMagickThreadValue method is:
%
% MagickBooleanType SetMagickThreadValue(MagickThreadKey key,
% const void *value)
%
% A description of each parameter follows:
%
% o key: the thread key.
%
% o value: the value.
%
*/
MagickExport MagickBooleanType SetMagickThreadValue(MagickThreadKey key,
const void *value)
{
#if defined(MAGICKCORE_THREAD_SUPPORT)
return(pthread_setspecific(key,value) == 0 ? MagickTrue : MagickFalse);
#elif defined(MAGICKCORE_WINDOWS_SUPPORT)
return(TlsSetValue(key,(void *) value) != 0 ? MagickTrue : MagickFalse);
#else
{
MagickThreadValue
*keys;
keys=(MagickThreadValue *) key;
keys->values[GetOpenMPThreadId()]=(void *) value;
}
return(MagickTrue);
#endif
}