Mutex stuff movibg to C
This commit is contained in:
parent
c9c2d7233c
commit
a83ff038f4
14
C/errors.c
14
C/errors.c
@ -1075,6 +1075,20 @@ Yap_Error(yap_error_number type, Term where, char *format,...)
|
|||||||
serious = TRUE;
|
serious = TRUE;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case EXISTENCE_ERROR_MUTEX:
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
Term ti[2];
|
||||||
|
|
||||||
|
i = strlen(tmpbuf);
|
||||||
|
ti[0] = MkAtomTerm(AtomMutex);
|
||||||
|
ti[1] = where;
|
||||||
|
nt[0] = Yap_MkApplTerm(FunctorExistenceError, 2, ti);
|
||||||
|
psize -= i;
|
||||||
|
fun = FunctorError;
|
||||||
|
serious = TRUE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case EXISTENCE_ERROR_VARIABLE:
|
case EXISTENCE_ERROR_VARIABLE:
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
167
C/threads.c
167
C/threads.c
@ -877,7 +877,11 @@ p_valid_thread( USES_REGS1 )
|
|||||||
typedef struct swi_mutex {
|
typedef struct swi_mutex {
|
||||||
UInt owners;
|
UInt owners;
|
||||||
Int tid_own;
|
Int tid_own;
|
||||||
|
MutexEntry *alias;
|
||||||
pthread_mutex_t m;
|
pthread_mutex_t m;
|
||||||
|
UInt timestamp;
|
||||||
|
struct swi_mutex *backbone; // chain of all mutexes
|
||||||
|
struct swi_mutex *prev, *next; // chain of locked mutexes
|
||||||
} SWIMutex;
|
} SWIMutex;
|
||||||
|
|
||||||
static SWIMutex *NewMutex(void) {
|
static SWIMutex *NewMutex(void) {
|
||||||
@ -887,11 +891,23 @@ static SWIMutex *NewMutex(void) {
|
|||||||
extern int pthread_mutexattr_setkind_np(pthread_mutexattr_t *attr, int kind);
|
extern int pthread_mutexattr_setkind_np(pthread_mutexattr_t *attr, int kind);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
LOCK(GLOBAL_MUT_ACCESS);
|
||||||
|
mutp = GLOBAL_FreeMutexes;
|
||||||
|
while (mutp) {
|
||||||
|
if ((Int)(mutp->owners) < 0) {
|
||||||
|
// just making sure
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
mutp = mutp->next;
|
||||||
|
}
|
||||||
|
if (mutp == NULL) {
|
||||||
mutp = (SWIMutex *)Yap_AllocCodeSpace(sizeof(SWIMutex));
|
mutp = (SWIMutex *)Yap_AllocCodeSpace(sizeof(SWIMutex));
|
||||||
if (mutp == NULL) {
|
if (mutp == NULL) {
|
||||||
return FALSE;
|
UNLOCK(GLOBAL_MUT_ACCESS);
|
||||||
}
|
return NULL;
|
||||||
|
} else {
|
||||||
pthread_mutexattr_init(&mat);
|
pthread_mutexattr_init(&mat);
|
||||||
|
mutp->timestamp = 0;
|
||||||
#if defined(HAVE_PTHREAD_MUTEXATTR_SETKIND_NP) && !defined(__MINGW32__)
|
#if defined(HAVE_PTHREAD_MUTEXATTR_SETKIND_NP) && !defined(__MINGW32__)
|
||||||
pthread_mutexattr_setkind_np(&mat, PTHREAD_MUTEX_RECURSIVE_NP);
|
pthread_mutexattr_setkind_np(&mat, PTHREAD_MUTEX_RECURSIVE_NP);
|
||||||
#else
|
#else
|
||||||
@ -900,8 +916,17 @@ static SWIMutex *NewMutex(void) {
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
pthread_mutex_init(&mutp->m, &mat);
|
pthread_mutex_init(&mutp->m, &mat);
|
||||||
|
}
|
||||||
|
mutp->backbone = GLOBAL_mutex_backbone;
|
||||||
|
GLOBAL_mutex_backbone = mutp;
|
||||||
|
} else {
|
||||||
|
// reuse existing mutex
|
||||||
|
mutp->timestamp++;
|
||||||
|
}
|
||||||
mutp->owners = 0;
|
mutp->owners = 0;
|
||||||
mutp->tid_own = 0;
|
mutp->tid_own = 0;
|
||||||
|
mutp->alias = NIL;
|
||||||
|
UNLOCK(GLOBAL_MUT_ACCESS);
|
||||||
return mutp;
|
return mutp;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -912,10 +937,15 @@ static SWIMutex *MutexOfTerm__(Term t USES_REGS){
|
|||||||
SWIMutex *mut = NULL;
|
SWIMutex *mut = NULL;
|
||||||
|
|
||||||
if (IsVarTerm(t1)) {
|
if (IsVarTerm(t1)) {
|
||||||
mut = NewMutex();
|
Yap_Error(INSTANTIATION_ERROR, t1, "mutex operation");
|
||||||
Yap_unify(MkAddressTerm(mut), ARG1);
|
return NULL;
|
||||||
} else if (IsIntegerTerm(t1)) {
|
} else if (IsApplTerm(t1) && FunctorOfTerm(t1) == FunctorMutex) {
|
||||||
mut = AddressOfTerm(t1);
|
mut = AddressOfTerm(ArgOfTerm(1,t1));
|
||||||
|
if ((Int)(mut->owners) < 0 ||
|
||||||
|
IntegerOfTerm(ArgOfTerm(2,t1)) != mut->timestamp) {
|
||||||
|
Yap_Error(EXISTENCE_ERROR_MUTEX, t1, "mutex access");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
} else if (IsAtomTerm(t1)) {
|
} else if (IsAtomTerm(t1)) {
|
||||||
mut = Yap_GetMutexFromProp(AtomOfTerm(t1));
|
mut = Yap_GetMutexFromProp(AtomOfTerm(t1));
|
||||||
if (!mut) {
|
if (!mut) {
|
||||||
@ -933,27 +963,33 @@ p_new_mutex( USES_REGS1 ){
|
|||||||
SWIMutex* mutp;
|
SWIMutex* mutp;
|
||||||
Term t1;
|
Term t1;
|
||||||
if (IsVarTerm((t1 = Deref(ARG1)))) {
|
if (IsVarTerm((t1 = Deref(ARG1)))) {
|
||||||
|
Term ts[2];
|
||||||
|
|
||||||
if (!(mutp = NewMutex()))
|
if (!(mutp = NewMutex()))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
return Yap_unify(ARG1, MkAddressTerm(mutp));
|
ts[0] = MkAddressTerm(mutp);
|
||||||
|
ts[1] = MkIntegerTerm(mutp->timestamp);
|
||||||
|
if (Yap_unify(ARG1, Yap_MkApplTerm(FunctorMutex, 2, ts) ) ) {
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
Yap_Error(UNINSTANTIATION_ERROR, t1, "mutex_create on an existing mutex");
|
||||||
|
return FALSE;
|
||||||
} else if(IsAtomTerm(t1)) {
|
} else if(IsAtomTerm(t1)) {
|
||||||
if (!(mutp = NewMutex()))
|
if (!(mutp = NewMutex()))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
return Yap_PutAtomMutex( AtomOfTerm(t1), mutp );
|
return Yap_PutAtomMutex( AtomOfTerm(t1), mutp );
|
||||||
} else if (IsAddressTerm(t1)) {
|
} else if (IsApplTerm(t1) && FunctorOfTerm(t1) == FunctorMutex) {
|
||||||
|
Yap_Error(UNINSTANTIATION_ERROR, t1, "mutex_create on an existing mutex");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @pred mutex_destroy(+ _MutexId_)
|
||||||
|
|
||||||
|
Destroy a mutex. After this call, _MutexId_ becomes invalid and
|
||||||
|
further references yield an `existence_error` exception.
|
||||||
|
*/
|
||||||
static Int p_destroy_mutex( USES_REGS1 )
|
static Int p_destroy_mutex( USES_REGS1 )
|
||||||
{
|
{
|
||||||
SWIMutex *mut = MutexOfTerm(Deref(ARG1));
|
SWIMutex *mut = MutexOfTerm(Deref(ARG1));
|
||||||
@ -961,7 +997,19 @@ p_new_mutex( USES_REGS1 ){
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
if (pthread_mutex_destroy(&mut->m) < 0)
|
if (pthread_mutex_destroy(&mut->m) < 0)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
Yap_FreeCodeSpace((void *)mut);
|
if (mut->alias) {
|
||||||
|
mut->alias->Mutex = NULL;
|
||||||
|
}
|
||||||
|
mut->owners = -1;
|
||||||
|
mut->tid_own = -1;
|
||||||
|
LOCK(GLOBAL_MUT_ACCESS);
|
||||||
|
if (GLOBAL_FreeMutexes)
|
||||||
|
mut->prev = GLOBAL_FreeMutexes->prev;
|
||||||
|
else
|
||||||
|
mut->prev = NULL;
|
||||||
|
mut->next = GLOBAL_FreeMutexes;
|
||||||
|
GLOBAL_FreeMutexes = mut;
|
||||||
|
UNLOCK(GLOBAL_MUT_ACCESS);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -976,11 +1024,17 @@ LockMutex( SWIMutex *mut USES_REGS)
|
|||||||
#endif
|
#endif
|
||||||
mut->owners++;
|
mut->owners++;
|
||||||
mut->tid_own = worker_id;
|
mut->tid_own = worker_id;
|
||||||
|
if (LOCAL_Mutexes)
|
||||||
|
mut->prev = LOCAL_Mutexes->prev;
|
||||||
|
else
|
||||||
|
mut->prev = NULL;
|
||||||
|
mut->next = LOCAL_Mutexes;
|
||||||
|
LOCAL_Mutexes = NULL;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
UnLockMutex( SWIMutex *mut )
|
UnLockMutex( SWIMutex *mut USES_REGS)
|
||||||
{
|
{
|
||||||
#if DEBUG_LOCKS
|
#if DEBUG_LOCKS
|
||||||
MUTEX_UNLOCK(&mut->m);
|
MUTEX_UNLOCK(&mut->m);
|
||||||
@ -989,9 +1043,39 @@ UnLockMutex( SWIMutex *mut )
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
#endif
|
#endif
|
||||||
mut->owners--;
|
mut->owners--;
|
||||||
|
if (mut->prev) {
|
||||||
|
mut->prev->next = mut->next;
|
||||||
|
} else {
|
||||||
|
LOCAL_Mutexes = mut->next;
|
||||||
|
if (mut->next)
|
||||||
|
mut->next->prev = NULL;
|
||||||
|
}
|
||||||
|
if (mut->next)
|
||||||
|
mut->next->prev = mut->prev;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @pred mutex_lock(+ _MutexId_)
|
||||||
|
|
||||||
|
|
||||||
|
Lock the mutex. Prolog mutexes are <em>recursive</em> mutexes: they
|
||||||
|
can be locked multiple times by the same thread. Only after unlocking
|
||||||
|
it as many times as it is locked, the mutex becomes available for
|
||||||
|
locking by other threads. If another thread has locked the mutex the
|
||||||
|
calling thread is suspended until to mutex is unlocked.
|
||||||
|
|
||||||
|
If _MutexId_ is an atom, and there is no current mutex with that
|
||||||
|
name, the mutex is created automatically using mutex_create/1. This
|
||||||
|
implies named mutexes need not be declared explicitly.
|
||||||
|
|
||||||
|
Please note that locking and unlocking mutexes should be paired
|
||||||
|
carefully. Especially make sure to unlock mutexes even if the protected
|
||||||
|
code fails or raises an exception. For most common cases use
|
||||||
|
with_mutex/2, which provides a safer way for handling Prolog-level
|
||||||
|
mutexes.
|
||||||
|
|
||||||
|
|
||||||
|
*/
|
||||||
static Int
|
static Int
|
||||||
p_lock_mutex( USES_REGS1 )
|
p_lock_mutex( USES_REGS1 )
|
||||||
{
|
{
|
||||||
@ -1001,6 +1085,14 @@ p_lock_mutex( USES_REGS1 )
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @pred mutex_trylock(+ _MutexId_)
|
||||||
|
|
||||||
|
|
||||||
|
As mutex_lock/1, but if the mutex is held by another thread, this
|
||||||
|
predicates fails immediately.
|
||||||
|
|
||||||
|
|
||||||
|
*/
|
||||||
static Int
|
static Int
|
||||||
p_trylock_mutex( USES_REGS1 )
|
p_trylock_mutex( USES_REGS1 )
|
||||||
{
|
{
|
||||||
@ -1015,15 +1107,40 @@ p_trylock_mutex( USES_REGS1 )
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @pred mutex_unlock(+ _MutexId_)
|
||||||
|
|
||||||
|
|
||||||
|
Unlock the mutex. This can only be called if the mutex is held by the
|
||||||
|
calling thread. If this is not the case, a `permission_error`
|
||||||
|
exception is raised.
|
||||||
|
|
||||||
|
|
||||||
|
*/
|
||||||
static Int
|
static Int
|
||||||
p_unlock_mutex( USES_REGS1 )
|
p_unlock_mutex( USES_REGS1 )
|
||||||
{
|
{
|
||||||
SWIMutex *mut = MutexOfTerm(Deref(ARG1));
|
SWIMutex *mut = MutexOfTerm(Deref(ARG1));
|
||||||
if (!mut || !UnLockMutex( mut ))
|
if (!mut || !UnLockMutex( mut PASS_REGS))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @pred with_mutex(+ _MutexId_, : _Goal_)
|
||||||
|
|
||||||
|
|
||||||
|
Execute _Goal_ while holding _MutexId_. If _Goal_ leaves
|
||||||
|
choicepoints, these are destroyed (as in once/1). The mutex is unlocked
|
||||||
|
regardless of whether _Goal_ succeeds, fails or raises an exception.
|
||||||
|
An exception thrown by _Goal_ is re-thrown after the mutex has been
|
||||||
|
successfully unlocked. See also `mutex_create/2`.
|
||||||
|
|
||||||
|
Although described in the thread-section, this predicate is also
|
||||||
|
available in the single-threaded version, where it behaves simply as
|
||||||
|
once/1.
|
||||||
|
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
static Int
|
static Int
|
||||||
p_with_mutex( USES_REGS1 )
|
p_with_mutex( USES_REGS1 )
|
||||||
{
|
{
|
||||||
@ -1084,7 +1201,7 @@ p_with_mutex( USES_REGS1 )
|
|||||||
}
|
}
|
||||||
end:
|
end:
|
||||||
excep = Yap_GetException();
|
excep = Yap_GetException();
|
||||||
if ( !UnLockMutex(mut) ) {
|
if ( !UnLockMutex(mut PASS_REGS) ) {
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
if (creeping) {
|
if (creeping) {
|
||||||
@ -1559,11 +1676,11 @@ void Yap_InitThreadPreds(void)
|
|||||||
*/
|
*/
|
||||||
Yap_InitCPred("$valid_thread", 1, p_valid_thread, 0);
|
Yap_InitCPred("$valid_thread", 1, p_valid_thread, 0);
|
||||||
Yap_InitCPred("mutex_create", 1, p_new_mutex, SafePredFlag);
|
Yap_InitCPred("mutex_create", 1, p_new_mutex, SafePredFlag);
|
||||||
Yap_InitCPred("$destroy_mutex", 1, p_destroy_mutex, SafePredFlag);
|
Yap_InitCPred("mutex_destroy", 1, p_destroy_mutex, SafePredFlag);
|
||||||
Yap_InitCPred("$lock_mutex", 1, p_lock_mutex, SafePredFlag);
|
Yap_InitCPred("mutex_lock", 1, p_lock_mutex, SafePredFlag);
|
||||||
Yap_InitCPred("$trylock_mutex", 1, p_trylock_mutex, SafePredFlag);
|
Yap_InitCPred("mutex_trylock", 1, p_trylock_mutex, SafePredFlag);
|
||||||
Yap_InitCPred("$unlock_mutex", 1, p_unlock_mutex, SafePredFlag);
|
Yap_InitCPred("mutex_unlock", 1, p_unlock_mutex, SafePredFlag);
|
||||||
Yap_InitCPred("$with_mutex", 2, p_with_mutex, MetaPredFlag);
|
Yap_InitCPred("with_mutex", 2, p_with_mutex, MetaPredFlag);
|
||||||
Yap_InitCPred("$with_with_mutex", 1, p_with_with_mutex, 0);
|
Yap_InitCPred("$with_with_mutex", 1, p_with_with_mutex, 0);
|
||||||
Yap_InitCPred("$unlock_with_mutex", 1, p_unlock_with_mutex, 0);
|
Yap_InitCPred("$unlock_with_mutex", 1, p_unlock_with_mutex, 0);
|
||||||
Yap_InitCPred("$mutex_info", 3, p_mutex_info, SafePredFlag);
|
Yap_InitCPred("$mutex_info", 3, p_mutex_info, SafePredFlag);
|
||||||
|
@ -1346,7 +1346,7 @@ IsTranslationProperty (int flags)
|
|||||||
p = RepMutexProp(p0 = p->NextOfPE);
|
p = RepMutexProp(p0 = p->NextOfPE);
|
||||||
READ_UNLOCK(ae->ARWLock);
|
READ_UNLOCK(ae->ARWLock);
|
||||||
if (p0 == NIL) return NULL;
|
if (p0 == NIL) return NULL;
|
||||||
return p;
|
return p->Mutex;
|
||||||
}
|
}
|
||||||
|
|
||||||
INLINE_ONLY inline EXTERN PropFlags IsMutexProperty (int);
|
INLINE_ONLY inline EXTERN PropFlags IsMutexProperty (int);
|
||||||
|
@ -125,3 +125,9 @@
|
|||||||
#define GLOBAL_FPreds Yap_global->FPreds_
|
#define GLOBAL_FPreds Yap_global->FPreds_
|
||||||
#endif /* LOW_PROF */
|
#endif /* LOW_PROF */
|
||||||
|
|
||||||
|
#if THREADS
|
||||||
|
#define GLOBAL_FreeMutexes Yap_global->FreeMutexes_
|
||||||
|
#define GLOBAL_mutex_backbone Yap_global->mutex_backbone_
|
||||||
|
#define GLOBAL_MUT_ACCESS Yap_global->MUT_ACCESS_
|
||||||
|
#endif
|
||||||
|
|
||||||
|
@ -91,6 +91,8 @@
|
|||||||
#define REMOTE_ArithError(wid) REMOTE(wid)->ArithError_
|
#define REMOTE_ArithError(wid) REMOTE(wid)->ArithError_
|
||||||
#define LOCAL_LastAssertedPred LOCAL->LastAssertedPred_
|
#define LOCAL_LastAssertedPred LOCAL->LastAssertedPred_
|
||||||
#define REMOTE_LastAssertedPred(wid) REMOTE(wid)->LastAssertedPred_
|
#define REMOTE_LastAssertedPred(wid) REMOTE(wid)->LastAssertedPred_
|
||||||
|
#define LOCAL_TmpPred LOCAL->TmpPred_
|
||||||
|
#define REMOTE_TmpPred(wid) REMOTE(wid)->TmpPred_
|
||||||
#define LOCAL_ScannerStack LOCAL->ScannerStack_
|
#define LOCAL_ScannerStack LOCAL->ScannerStack_
|
||||||
#define REMOTE_ScannerStack(wid) REMOTE(wid)->ScannerStack_
|
#define REMOTE_ScannerStack(wid) REMOTE(wid)->ScannerStack_
|
||||||
#define LOCAL_ScannerExtraBlocks LOCAL->ScannerExtraBlocks_
|
#define LOCAL_ScannerExtraBlocks LOCAL->ScannerExtraBlocks_
|
||||||
@ -424,6 +426,9 @@
|
|||||||
|
|
||||||
#define LOCAL_CurSlot LOCAL->CurSlot_
|
#define LOCAL_CurSlot LOCAL->CurSlot_
|
||||||
#define REMOTE_CurSlot(wid) REMOTE(wid)->CurSlot_
|
#define REMOTE_CurSlot(wid) REMOTE(wid)->CurSlot_
|
||||||
|
|
||||||
|
#define LOCAL_Mutexes LOCAL->Mutexes_
|
||||||
|
#define REMOTE_Mutexes(wid) REMOTE(wid)->Mutexes_
|
||||||
#define LOCAL_SourceModule LOCAL->SourceModule_
|
#define LOCAL_SourceModule LOCAL->SourceModule_
|
||||||
#define REMOTE_SourceModule(wid) REMOTE(wid)->SourceModule_
|
#define REMOTE_SourceModule(wid) REMOTE(wid)->SourceModule_
|
||||||
#define LOCAL_MAX_SIZE LOCAL->MAX_SIZE_
|
#define LOCAL_MAX_SIZE LOCAL->MAX_SIZE_
|
||||||
|
@ -124,4 +124,10 @@ typedef struct global_data {
|
|||||||
FILE* FProf_;
|
FILE* FProf_;
|
||||||
FILE* FPreds_;
|
FILE* FPreds_;
|
||||||
#endif /* LOW_PROF */
|
#endif /* LOW_PROF */
|
||||||
|
|
||||||
|
#if THREADS
|
||||||
|
struct swi_mutex* FreeMutexes_;
|
||||||
|
struct swi_mutex* mutex_backbone_;
|
||||||
|
lockvar MUT_ACCESS_;
|
||||||
|
#endif
|
||||||
} w_shared;
|
} w_shared;
|
||||||
|
@ -52,6 +52,7 @@ typedef struct worker_local {
|
|||||||
Int DepthArenas_;
|
Int DepthArenas_;
|
||||||
int ArithError_;
|
int ArithError_;
|
||||||
struct pred_entry* LastAssertedPred_;
|
struct pred_entry* LastAssertedPred_;
|
||||||
|
struct pred_entry* TmpPred_;
|
||||||
char* ScannerStack_;
|
char* ScannerStack_;
|
||||||
struct scanner_extra_alloc* ScannerExtraBlocks_;
|
struct scanner_extra_alloc* ScannerExtraBlocks_;
|
||||||
struct DB_TERM* BallTerm_;
|
struct DB_TERM* BallTerm_;
|
||||||
@ -239,6 +240,8 @@ typedef struct worker_local {
|
|||||||
struct scan_atoms* search_atoms_;
|
struct scan_atoms* search_atoms_;
|
||||||
|
|
||||||
yhandle_t CurSlot_;
|
yhandle_t CurSlot_;
|
||||||
|
|
||||||
|
struct swi_mutex* Mutexes_;
|
||||||
Term SourceModule_;
|
Term SourceModule_;
|
||||||
size_t MAX_SIZE_;
|
size_t MAX_SIZE_;
|
||||||
} w_local;
|
} w_local;
|
||||||
|
@ -189,6 +189,7 @@
|
|||||||
AtomMultiple = Yap_FullLookupAtom("multiple");
|
AtomMultiple = Yap_FullLookupAtom("multiple");
|
||||||
AtomMutable = Yap_LookupAtom("mutable");
|
AtomMutable = Yap_LookupAtom("mutable");
|
||||||
AtomMutableVariable = Yap_FullLookupAtom("$mutable_variable");
|
AtomMutableVariable = Yap_FullLookupAtom("$mutable_variable");
|
||||||
|
AtomMutex = Yap_LookupAtom("mutex");
|
||||||
AtomMyddasDB = Yap_FullLookupAtom("$myddas_db");
|
AtomMyddasDB = Yap_FullLookupAtom("$myddas_db");
|
||||||
AtomMyddasGoal = Yap_FullLookupAtom("$myddas_goal");
|
AtomMyddasGoal = Yap_FullLookupAtom("$myddas_goal");
|
||||||
AtomMyddasHost = Yap_FullLookupAtom("$myddas_host");
|
AtomMyddasHost = Yap_FullLookupAtom("$myddas_host");
|
||||||
@ -435,6 +436,7 @@
|
|||||||
FunctorModule = Yap_MkFunctor(AtomColomn,2);
|
FunctorModule = Yap_MkFunctor(AtomColomn,2);
|
||||||
FunctorMultiFileClause = Yap_MkFunctor(AtomMfClause,5);
|
FunctorMultiFileClause = Yap_MkFunctor(AtomMfClause,5);
|
||||||
FunctorMutable = Yap_MkFunctor(AtomMutableVariable,(sizeof(timed_var)/sizeof(CELL)));
|
FunctorMutable = Yap_MkFunctor(AtomMutableVariable,(sizeof(timed_var)/sizeof(CELL)));
|
||||||
|
FunctorMutex = Yap_MkFunctor(AtomMutex,2);
|
||||||
FunctorNotImplemented = Yap_MkFunctor(AtomNotImplemented,2);
|
FunctorNotImplemented = Yap_MkFunctor(AtomNotImplemented,2);
|
||||||
FunctorNBQueue = Yap_MkFunctor(AtomQueue,4);
|
FunctorNBQueue = Yap_MkFunctor(AtomQueue,4);
|
||||||
FunctorNot = Yap_MkFunctor(AtomNot,1);
|
FunctorNot = Yap_MkFunctor(AtomNot,1);
|
||||||
|
@ -124,4 +124,10 @@ static void InitGlobal(void) {
|
|||||||
GLOBAL_FProf = NULL;
|
GLOBAL_FProf = NULL;
|
||||||
GLOBAL_FPreds = NULL;
|
GLOBAL_FPreds = NULL;
|
||||||
#endif /* LOW_PROF */
|
#endif /* LOW_PROF */
|
||||||
|
|
||||||
|
#if THREADS
|
||||||
|
GLOBAL_FreeMutexes = NULL;
|
||||||
|
GLOBAL_mutex_backbone = NULL;
|
||||||
|
INIT_LOCK(GLOBAL_MUT_ACCESS);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -52,6 +52,7 @@ static void InitWorker(int wid) {
|
|||||||
REMOTE_DepthArenas(wid) = 0;
|
REMOTE_DepthArenas(wid) = 0;
|
||||||
REMOTE_ArithError(wid) = FALSE;
|
REMOTE_ArithError(wid) = FALSE;
|
||||||
REMOTE_LastAssertedPred(wid) = NULL;
|
REMOTE_LastAssertedPred(wid) = NULL;
|
||||||
|
REMOTE_TmpPred(wid) = NULL;
|
||||||
REMOTE_ScannerStack(wid) = NULL;
|
REMOTE_ScannerStack(wid) = NULL;
|
||||||
REMOTE_ScannerExtraBlocks(wid) = NULL;
|
REMOTE_ScannerExtraBlocks(wid) = NULL;
|
||||||
REMOTE_BallTerm(wid) = NULL;
|
REMOTE_BallTerm(wid) = NULL;
|
||||||
@ -239,6 +240,8 @@ static void InitWorker(int wid) {
|
|||||||
|
|
||||||
|
|
||||||
REMOTE_CurSlot(wid) = 0;
|
REMOTE_CurSlot(wid) = 0;
|
||||||
|
|
||||||
|
REMOTE_Mutexes(wid) = NULL;
|
||||||
REMOTE_SourceModule(wid) = 0;
|
REMOTE_SourceModule(wid) = 0;
|
||||||
REMOTE_MAX_SIZE(wid) = 1024L;
|
REMOTE_MAX_SIZE(wid) = 1024L;
|
||||||
}
|
}
|
||||||
|
@ -189,6 +189,7 @@
|
|||||||
AtomMultiple = AtomAdjust(AtomMultiple);
|
AtomMultiple = AtomAdjust(AtomMultiple);
|
||||||
AtomMutable = AtomAdjust(AtomMutable);
|
AtomMutable = AtomAdjust(AtomMutable);
|
||||||
AtomMutableVariable = AtomAdjust(AtomMutableVariable);
|
AtomMutableVariable = AtomAdjust(AtomMutableVariable);
|
||||||
|
AtomMutex = AtomAdjust(AtomMutex);
|
||||||
AtomMyddasDB = AtomAdjust(AtomMyddasDB);
|
AtomMyddasDB = AtomAdjust(AtomMyddasDB);
|
||||||
AtomMyddasGoal = AtomAdjust(AtomMyddasGoal);
|
AtomMyddasGoal = AtomAdjust(AtomMyddasGoal);
|
||||||
AtomMyddasHost = AtomAdjust(AtomMyddasHost);
|
AtomMyddasHost = AtomAdjust(AtomMyddasHost);
|
||||||
@ -435,6 +436,7 @@
|
|||||||
FunctorModule = FuncAdjust(FunctorModule);
|
FunctorModule = FuncAdjust(FunctorModule);
|
||||||
FunctorMultiFileClause = FuncAdjust(FunctorMultiFileClause);
|
FunctorMultiFileClause = FuncAdjust(FunctorMultiFileClause);
|
||||||
FunctorMutable = FuncAdjust(FunctorMutable);
|
FunctorMutable = FuncAdjust(FunctorMutable);
|
||||||
|
FunctorMutex = FuncAdjust(FunctorMutex);
|
||||||
FunctorNotImplemented = FuncAdjust(FunctorNotImplemented);
|
FunctorNotImplemented = FuncAdjust(FunctorNotImplemented);
|
||||||
FunctorNBQueue = FuncAdjust(FunctorNBQueue);
|
FunctorNBQueue = FuncAdjust(FunctorNBQueue);
|
||||||
FunctorNot = FuncAdjust(FunctorNot);
|
FunctorNot = FuncAdjust(FunctorNot);
|
||||||
|
@ -124,4 +124,10 @@ static void RestoreGlobal(void) {
|
|||||||
|
|
||||||
|
|
||||||
#endif /* LOW_PROF */
|
#endif /* LOW_PROF */
|
||||||
|
|
||||||
|
#if THREADS
|
||||||
|
|
||||||
|
|
||||||
|
REINIT_LOCK(GLOBAL_MUT_ACCESS);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -54,6 +54,7 @@ static void RestoreWorker(int wid USES_REGS) {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
RestoreBallTerm(wid);
|
RestoreBallTerm(wid);
|
||||||
|
|
||||||
|
|
||||||
@ -241,4 +242,6 @@ static void RestoreWorker(int wid USES_REGS) {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -376,6 +376,8 @@
|
|||||||
#define AtomMutable Yap_heap_regs->AtomMutable_
|
#define AtomMutable Yap_heap_regs->AtomMutable_
|
||||||
Atom AtomMutableVariable_;
|
Atom AtomMutableVariable_;
|
||||||
#define AtomMutableVariable Yap_heap_regs->AtomMutableVariable_
|
#define AtomMutableVariable Yap_heap_regs->AtomMutableVariable_
|
||||||
|
Atom AtomMutex_;
|
||||||
|
#define AtomMutex Yap_heap_regs->AtomMutex_
|
||||||
Atom AtomMyddasDB_;
|
Atom AtomMyddasDB_;
|
||||||
#define AtomMyddasDB Yap_heap_regs->AtomMyddasDB_
|
#define AtomMyddasDB Yap_heap_regs->AtomMyddasDB_
|
||||||
Atom AtomMyddasGoal_;
|
Atom AtomMyddasGoal_;
|
||||||
@ -868,6 +870,8 @@
|
|||||||
#define FunctorMultiFileClause Yap_heap_regs->FunctorMultiFileClause_
|
#define FunctorMultiFileClause Yap_heap_regs->FunctorMultiFileClause_
|
||||||
Functor FunctorMutable_;
|
Functor FunctorMutable_;
|
||||||
#define FunctorMutable Yap_heap_regs->FunctorMutable_
|
#define FunctorMutable Yap_heap_regs->FunctorMutable_
|
||||||
|
Functor FunctorMutex_;
|
||||||
|
#define FunctorMutex Yap_heap_regs->FunctorMutex_
|
||||||
Functor FunctorNotImplemented_;
|
Functor FunctorNotImplemented_;
|
||||||
#define FunctorNotImplemented Yap_heap_regs->FunctorNotImplemented_
|
#define FunctorNotImplemented Yap_heap_regs->FunctorNotImplemented_
|
||||||
Functor FunctorNBQueue_;
|
Functor FunctorNBQueue_;
|
||||||
|
@ -55,6 +55,7 @@ typedef enum
|
|||||||
EVALUATION_ERROR_ZERO_DIVISOR,
|
EVALUATION_ERROR_ZERO_DIVISOR,
|
||||||
EXISTENCE_ERROR_ARRAY,
|
EXISTENCE_ERROR_ARRAY,
|
||||||
EXISTENCE_ERROR_KEY,
|
EXISTENCE_ERROR_KEY,
|
||||||
|
EXISTENCE_ERROR_MUTEX,
|
||||||
EXISTENCE_ERROR_SOURCE_SINK,
|
EXISTENCE_ERROR_SOURCE_SINK,
|
||||||
EXISTENCE_ERROR_STREAM,
|
EXISTENCE_ERROR_STREAM,
|
||||||
EXISTENCE_ERROR_VARIABLE,
|
EXISTENCE_ERROR_VARIABLE,
|
||||||
@ -121,6 +122,7 @@ typedef enum
|
|||||||
TYPE_ERROR_UBYTE,
|
TYPE_ERROR_UBYTE,
|
||||||
TYPE_ERROR_UCHAR,
|
TYPE_ERROR_UCHAR,
|
||||||
TYPE_ERROR_VARIABLE,
|
TYPE_ERROR_VARIABLE,
|
||||||
|
UNINSTANTIATION_ERROR,
|
||||||
UNKNOWN_ERROR
|
UNKNOWN_ERROR
|
||||||
} yap_error_number;
|
} yap_error_number;
|
||||||
|
|
||||||
|
@ -194,6 +194,7 @@ A MultiFile F "$mf"
|
|||||||
A Multiple F "multiple"
|
A Multiple F "multiple"
|
||||||
A Mutable N "mutable"
|
A Mutable N "mutable"
|
||||||
A MutableVariable F "$mutable_variable"
|
A MutableVariable F "$mutable_variable"
|
||||||
|
A Mutex N "mutex"
|
||||||
A MyddasDB F "$myddas_db"
|
A MyddasDB F "$myddas_db"
|
||||||
A MyddasGoal F "$myddas_goal"
|
A MyddasGoal F "$myddas_goal"
|
||||||
A MyddasHost F "$myddas_host"
|
A MyddasHost F "$myddas_host"
|
||||||
@ -440,6 +441,7 @@ F Minus Minus 2
|
|||||||
F Module Colomn 2
|
F Module Colomn 2
|
||||||
F MultiFileClause MfClause 5
|
F MultiFileClause MfClause 5
|
||||||
F Mutable MutableVariable (sizeof(timed_var)/sizeof(CELL))
|
F Mutable MutableVariable (sizeof(timed_var)/sizeof(CELL))
|
||||||
|
F Mutex Mutex 2
|
||||||
F NotImplemented NotImplemented 2
|
F NotImplemented NotImplemented 2
|
||||||
F NBQueue Queue 4
|
F NBQueue Queue 4
|
||||||
F Not Not 1
|
F Not Not 1
|
||||||
|
@ -146,6 +146,12 @@ FILE* FProf =NULL
|
|||||||
FILE* FPreds =NULL
|
FILE* FPreds =NULL
|
||||||
#endif /* LOW_PROF */
|
#endif /* LOW_PROF */
|
||||||
|
|
||||||
|
// Mutexes
|
||||||
|
#if THREADS
|
||||||
|
struct swi_mutex* FreeMutexes =NULL
|
||||||
|
struct swi_mutex* mutex_backbone =NULL
|
||||||
|
lockvar MUT_ACCESS MkLock
|
||||||
|
#endif
|
||||||
|
|
||||||
END_GLOBAL_DATA
|
END_GLOBAL_DATA
|
||||||
|
|
||||||
|
@ -55,7 +55,6 @@ Int DepthArenas =0
|
|||||||
int ArithError =FALSE
|
int ArithError =FALSE
|
||||||
struct pred_entry* LastAssertedPred =NULL
|
struct pred_entry* LastAssertedPred =NULL
|
||||||
struct pred_entry* TmpPred =NULL
|
struct pred_entry* TmpPred =NULL
|
||||||
struct pred_entry* LastAssertedPred =NULL
|
|
||||||
char* ScannerStack =NULL
|
char* ScannerStack =NULL
|
||||||
struct scanner_extra_alloc* ScannerExtraBlocks =NULL
|
struct scanner_extra_alloc* ScannerExtraBlocks =NULL
|
||||||
struct DB_TERM* BallTerm =NULL RestoreBallTerm(wid)
|
struct DB_TERM* BallTerm =NULL RestoreBallTerm(wid)
|
||||||
@ -276,6 +275,8 @@ struct scan_atoms* search_atoms void
|
|||||||
// Slots
|
// Slots
|
||||||
yhandle_t CurSlot =0
|
yhandle_t CurSlot =0
|
||||||
|
|
||||||
|
// Mutexes
|
||||||
|
struct swi_mutex* Mutexes =NULL
|
||||||
|
|
||||||
Term SourceModule =0
|
Term SourceModule =0
|
||||||
|
|
||||||
|
@ -163,6 +163,11 @@ optimizer_initialize(1,evaluate,progress)
|
|||||||
*/
|
*/
|
||||||
optimizer_initialize(N,Call_Evaluate,Call_Progress) :-
|
optimizer_initialize(N,Call_Evaluate,Call_Progress) :-
|
||||||
optimizer_initialize(N,user,Call_Evaluate,Call_Progress).
|
optimizer_initialize(N,user,Call_Evaluate,Call_Progress).
|
||||||
|
|
||||||
|
optimizer_initialize(N,Module,Call_Evaluate,Call_Progress) :-
|
||||||
|
optimizer_finalize,
|
||||||
|
!,
|
||||||
|
optimizer_initialize(N,Module,Call_Evaluate,Call_Progress).
|
||||||
optimizer_initialize(N,Module,Call_Evaluate,Call_Progress) :-
|
optimizer_initialize(N,Module,Call_Evaluate,Call_Progress) :-
|
||||||
\+ initialized,
|
\+ initialized,
|
||||||
|
|
||||||
|
@ -342,8 +342,8 @@ print_message(_, Term) :-
|
|||||||
current_prolog_flag(verbose, silent), !.
|
current_prolog_flag(verbose, silent), !.
|
||||||
'$print_system_message'(Term, Level, Lines) :-
|
'$print_system_message'(Term, Level, Lines) :-
|
||||||
( Level == error -> Term \= error(syntax_error(_), _) ; Level == warning ),
|
( Level == error -> Term \= error(syntax_error(_), _) ; Level == warning ),
|
||||||
'$messages':prefix(Level, LinePrefix, Stream, LinesF, Lines2),
|
'$messages':prefix(Level, LinePrefix, Stream, Lines2, Lines),
|
||||||
'$messages':file_location(Lines2, Lines), !,
|
'$messages':file_location(LinesF, Lines2), !,
|
||||||
flush_output(user_output),
|
flush_output(user_output),
|
||||||
flush_output(user_error),
|
flush_output(user_error),
|
||||||
print_message_lines(Stream, LinePrefix, [nl|LinesF]).
|
print_message_lines(Stream, LinePrefix, [nl|LinesF]).
|
||||||
|
@ -68,13 +68,12 @@ handling in YAP:
|
|||||||
|
|
||||||
file_location -->
|
file_location -->
|
||||||
{ source_location(FileName, LN) },
|
{ source_location(FileName, LN) },
|
||||||
file_position(FileName,LN),
|
file_position(FileName,LN).
|
||||||
[ nl ].
|
|
||||||
|
|
||||||
file_position(user_input,LN) -->
|
file_position(user_input,LN) -->
|
||||||
[ 'at line ~d in user_input,' - [LN] ].
|
[ 'user_input:~d:0: ' - [LN] ].
|
||||||
file_position(FileName,LN) -->
|
file_position(FileName,LN) -->
|
||||||
[ 'at line ~d in ~a,' - [LN,FileName] ].
|
[ '~a:~d:0: ' - [FileName,LN] ].
|
||||||
|
|
||||||
translate_message(Term) -->
|
translate_message(Term) -->
|
||||||
generate_message(Term), !.
|
generate_message(Term), !.
|
||||||
@ -238,6 +237,8 @@ system_message(error(existence_error(directory,Key), Where)) -->
|
|||||||
[ 'EXISTENCE ERROR- ~w: ~w not an existing directory' - [Where,Key] ].
|
[ 'EXISTENCE ERROR- ~w: ~w not an existing directory' - [Where,Key] ].
|
||||||
system_message(error(existence_error(key,Key), Where)) -->
|
system_message(error(existence_error(key,Key), Where)) -->
|
||||||
[ 'EXISTENCE ERROR- ~w: ~w not an existing key' - [Where,Key] ].
|
[ 'EXISTENCE ERROR- ~w: ~w not an existing key' - [Where,Key] ].
|
||||||
|
system_message(error(existence_error(mutex,Key), Where)) -->
|
||||||
|
[ 'EXISTENCE ERROR- ~w: ~w is an erased mutex' - [Where,Key] ].
|
||||||
system_message(existence_error(prolog_flag,F)) -->
|
system_message(existence_error(prolog_flag,F)) -->
|
||||||
[ 'Prolog Flag ~w: new Prolog flags must be created using create_prolog_flag/3.' - [F] ].
|
[ 'Prolog Flag ~w: new Prolog flags must be created using create_prolog_flag/3.' - [F] ].
|
||||||
system_message(error(existence_error(prolog_flag,P), Where)) --> !,
|
system_message(error(existence_error(prolog_flag,P), Where)) --> !,
|
||||||
@ -624,22 +625,22 @@ print_message_line(S, [Fmt|T0], T) :-
|
|||||||
prefix(help, '', user_error) --> [].
|
prefix(help, '', user_error) --> [].
|
||||||
prefix(query, '', user_error) --> [].
|
prefix(query, '', user_error) --> [].
|
||||||
prefix(debug, '', user_output) --> [].
|
prefix(debug, '', user_output) --> [].
|
||||||
prefix(warning, '% ', user_error) -->
|
prefix(warning, '', user_error) -->
|
||||||
{ thread_self(Id) },
|
{ thread_self(Id) },
|
||||||
( { Id == main }
|
( { Id == main }
|
||||||
-> [ 'Warning: ', nl ]
|
-> [ 'warning: ', nl ]
|
||||||
; { atom(Id) }
|
; { atom(Id) }
|
||||||
-> ['Warning: [Thread ~a ]' - [Id], nl ]
|
-> ['warning: [Thread ~a ]' - [Id], nl ]
|
||||||
; ['Warning: [Thread ~d ]' - [Id], nl ]
|
; ['warning: [Thread ~d ]' - [Id], nl ]
|
||||||
).
|
).
|
||||||
prefix(error, '', user_error) -->
|
prefix(error, '', user_error) -->
|
||||||
{ recorded(sp_info,local_sp(P,_,_,_),_) },
|
{ recorded(sp_info,local_sp(P,_,_,_),_) },
|
||||||
{ thread_self(Id) },
|
{ thread_self(Id) },
|
||||||
( { Id == main }
|
( { Id == main }
|
||||||
-> [ 'ERROR at ' ]
|
-> [ 'error at ' ]
|
||||||
; { atom(Id) }
|
; { atom(Id) }
|
||||||
-> [ 'ERROR [ Thread ~a ] at ' - [Id] ]
|
-> [ 'error [ Thread ~a ] at ' - [Id] ]
|
||||||
; [ 'ERROR [ Thread ~d ] at ' - [Id] ]
|
; [ 'error [ Thread ~d ] at ' - [Id] ]
|
||||||
),
|
),
|
||||||
'$hacks':display_pc(P),
|
'$hacks':display_pc(P),
|
||||||
!,
|
!,
|
||||||
@ -647,10 +648,10 @@ prefix(error, ' ', user_error) -->
|
|||||||
prefix(error, '', user_error) -->
|
prefix(error, '', user_error) -->
|
||||||
{ thread_self(Id) },
|
{ thread_self(Id) },
|
||||||
( { Id == main }
|
( { Id == main }
|
||||||
-> [ 'ERROR!!', nl ]
|
-> [ 'error!!', nl ]
|
||||||
; { atom(Id) }
|
; { atom(Id) }
|
||||||
-> [ 'ERROR!! [ Thread ~a ]' - [Id], nl ]
|
-> [ 'error!! [ Thread ~a ]' - [Id], nl ]
|
||||||
; [ 'ERROR!! [ Thread ~d ]' - [Id], nl ]
|
; [ 'error!! [ Thread ~d ]' - [Id], nl ]
|
||||||
).
|
).
|
||||||
prefix(banner, '', user_error) --> [].
|
prefix(banner, '', user_error) --> [].
|
||||||
prefix(informational, '~*|% '-[LC], user_error) -->
|
prefix(informational, '~*|% '-[LC], user_error) -->
|
||||||
|
164
pl/threads.yap
164
pl/threads.yap
@ -632,11 +632,6 @@ current_thread(Id, Status) :-
|
|||||||
'$thread_id_alias'(Id, Id).
|
'$thread_id_alias'(Id, Id).
|
||||||
|
|
||||||
|
|
||||||
'$mutex_id_alias'(Id, Alias) :-
|
|
||||||
recorded('$mutex_alias', [Id|Alias], _), !.
|
|
||||||
'$mutex_id_alias'(Id, Id).
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
thread_property(Prop) :-
|
thread_property(Prop) :-
|
||||||
'$check_thread_property'(Prop, thread_property(Prop)),
|
'$check_thread_property'(Prop, thread_property(Prop)),
|
||||||
@ -910,117 +905,6 @@ mutex_create(Id, Options) :-
|
|||||||
'$mutex_option'(Option, _, Goal) :-
|
'$mutex_option'(Option, _, Goal) :-
|
||||||
'$do_error'(domain_error(mutex_option, Option), Goal).
|
'$do_error'(domain_error(mutex_option, Option), Goal).
|
||||||
|
|
||||||
/*
|
|
||||||
mutex_create(V) :-
|
|
||||||
var(V), !,
|
|
||||||
'$new_mutex'(V),
|
|
||||||
recorda('$mutex_alias',[V|V],_).
|
|
||||||
mutex_create(A) :-
|
|
||||||
atom(A),
|
|
||||||
recorded('$mutex_alias',[_|A],_), !,
|
|
||||||
'$do_error'(permission_error(create,mutex,A),mutex_create(A)).
|
|
||||||
mutex_create(A) :-
|
|
||||||
atom(A), !,
|
|
||||||
'$new_mutex'(Id),
|
|
||||||
recorda('$mutex_alias',[Id|A],_).
|
|
||||||
mutex_create(V) :-
|
|
||||||
'$do_error'(type_error(atom,V),mutex_create(V)).
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** @pred mutex_destroy(+ _MutexId_)
|
|
||||||
|
|
||||||
|
|
||||||
Destroy a mutex. After this call, _MutexId_ becomes invalid and
|
|
||||||
further references yield an `existence_error` exception.
|
|
||||||
|
|
||||||
|
|
||||||
*/
|
|
||||||
mutex_destroy(Mutex) :-
|
|
||||||
'$check_mutex_or_alias'(Mutex, mutex_destroy(Mutex)),
|
|
||||||
'$mutex_id_alias'(Id, Mutex),
|
|
||||||
'$destroy_mutex'(Id),
|
|
||||||
'$erase_mutex_info'(Id).
|
|
||||||
|
|
||||||
'$erase_mutex_info'(Id) :-
|
|
||||||
recorded('$mutex_alias',[Id|_],R),
|
|
||||||
erase(R),
|
|
||||||
fail.
|
|
||||||
'$erase_mutex_info'(_).
|
|
||||||
|
|
||||||
|
|
||||||
/** @pred mutex_lock(+ _MutexId_)
|
|
||||||
|
|
||||||
|
|
||||||
Lock the mutex. Prolog mutexes are <em>recursive</em> mutexes: they
|
|
||||||
can be locked multiple times by the same thread. Only after unlocking
|
|
||||||
it as many times as it is locked, the mutex becomes available for
|
|
||||||
locking by other threads. If another thread has locked the mutex the
|
|
||||||
calling thread is suspended until to mutex is unlocked.
|
|
||||||
|
|
||||||
If _MutexId_ is an atom, and there is no current mutex with that
|
|
||||||
name, the mutex is created automatically using mutex_create/1. This
|
|
||||||
implies named mutexes need not be declared explicitly.
|
|
||||||
|
|
||||||
Please note that locking and unlocking mutexes should be paired
|
|
||||||
carefully. Especially make sure to unlock mutexes even if the protected
|
|
||||||
code fails or raises an exception. For most common cases use
|
|
||||||
with_mutex/2, which provides a safer way for handling Prolog-level
|
|
||||||
mutexes.
|
|
||||||
|
|
||||||
|
|
||||||
*/
|
|
||||||
mutex_lock(V) :-
|
|
||||||
var(V), !,
|
|
||||||
'$do_error'(instantiation_error,mutex_lock(V)).
|
|
||||||
mutex_lock(A) :-
|
|
||||||
recorded('$mutex_alias',[Id|A],_), !,
|
|
||||||
'$lock_mutex'(Id).
|
|
||||||
mutex_lock(A) :-
|
|
||||||
atom(A), !,
|
|
||||||
mutex_create(A),
|
|
||||||
mutex_lock(A).
|
|
||||||
mutex_lock(V) :-
|
|
||||||
'$do_error'(type_error(mutex,V),mutex_lock(V)).
|
|
||||||
|
|
||||||
/** @pred mutex_trylock(+ _MutexId_)
|
|
||||||
|
|
||||||
|
|
||||||
As mutex_lock/1, but if the mutex is held by another thread, this
|
|
||||||
predicates fails immediately.
|
|
||||||
|
|
||||||
|
|
||||||
*/
|
|
||||||
mutex_trylock(V) :-
|
|
||||||
var(V), !,
|
|
||||||
'$do_error'(instantiation_error,mutex_trylock(V)).
|
|
||||||
mutex_trylock(A) :-
|
|
||||||
recorded('$mutex_alias',[Id|A],_), !,
|
|
||||||
'$trylock_mutex'(Id).
|
|
||||||
mutex_trylock(A) :-
|
|
||||||
atom(A), !,
|
|
||||||
mutex_create(A),
|
|
||||||
mutex_trylock(A).
|
|
||||||
mutex_trylock(V) :-
|
|
||||||
'$do_error'(type_error(mutex,V),mutex_trylock(V)).
|
|
||||||
|
|
||||||
/** @pred mutex_unlock(+ _MutexId_)
|
|
||||||
|
|
||||||
|
|
||||||
Unlock the mutex. This can only be called if the mutex is held by the
|
|
||||||
calling thread. If this is not the case, a `permission_error`
|
|
||||||
exception is raised.
|
|
||||||
|
|
||||||
|
|
||||||
*/
|
|
||||||
mutex_unlock(Mutex) :-
|
|
||||||
'$check_mutex_or_alias'(Mutex, mutex_unlock(Mutex)),
|
|
||||||
'$mutex_id_alias'(Id, Mutex),
|
|
||||||
( '$unlock_mutex'(Id) ->
|
|
||||||
true
|
|
||||||
;
|
|
||||||
'$do_error'(permission_error(unlock,mutex,Mutex),mutex_unlock(Mutex))
|
|
||||||
).
|
|
||||||
|
|
||||||
/** @pred mutex_unlock_all
|
/** @pred mutex_unlock_all
|
||||||
|
|
||||||
|
|
||||||
@ -1048,54 +932,6 @@ mutex_unlock_all :-
|
|||||||
'$unlock_mutex'(Id),
|
'$unlock_mutex'(Id),
|
||||||
'$mutex_unlock_all'(Id).
|
'$mutex_unlock_all'(Id).
|
||||||
|
|
||||||
/** @pred with_mutex(+ _MutexId_, : _Goal_)
|
|
||||||
|
|
||||||
|
|
||||||
Execute _Goal_ while holding _MutexId_. If _Goal_ leaves
|
|
||||||
choicepoints, these are destroyed (as in once/1). The mutex is unlocked
|
|
||||||
regardless of whether _Goal_ succeeds, fails or raises an exception.
|
|
||||||
An exception thrown by _Goal_ is re-thrown after the mutex has been
|
|
||||||
successfully unlocked. See also `mutex_create/2`.
|
|
||||||
|
|
||||||
Although described in the thread-section, this predicate is also
|
|
||||||
available in the single-threaded version, where it behaves simply as
|
|
||||||
once/1.
|
|
||||||
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
with_mutex(M, G) :-
|
|
||||||
( recorded('$mutex_alias',[Id|M],_) ->
|
|
||||||
'$with_mutex'(Id, G )
|
|
||||||
;
|
|
||||||
atom(M ) ->
|
|
||||||
mutex_create(Id, [alias(M)]),
|
|
||||||
'$with_mutex'(M, G )
|
|
||||||
;
|
|
||||||
integer(M) ->
|
|
||||||
'$with_mutex'(M, G )
|
|
||||||
;
|
|
||||||
'$do_error'(type_error(mutex,M), with_mutex(M, G))
|
|
||||||
), nonvar(G). % preserve env.
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
with_mutex(M, G) :-
|
|
||||||
( '$no_threads' ->
|
|
||||||
once(G)
|
|
||||||
;
|
|
||||||
mutex_lock(M),
|
|
||||||
var(G) -> mutex_unlock(M), '$do_error'(instantiation_error,with_mutex(M, G))
|
|
||||||
;
|
|
||||||
\+ callable(G) ->
|
|
||||||
mutex_unlock(M), '$do_error'(type_error(callable,G),with_mutex(M, G))
|
|
||||||
;
|
|
||||||
catch('$execute'(G), E, (mutex_unlock(M), throw(E))) ->
|
|
||||||
mutex_unlock(M)
|
|
||||||
; mutex_unlock(M),
|
|
||||||
fail
|
|
||||||
).
|
|
||||||
*/
|
|
||||||
/** @pred current_mutex(? _MutexId_, ? _ThreadId_, ? _Count_)
|
/** @pred current_mutex(? _MutexId_, ? _ThreadId_, ? _Count_)
|
||||||
|
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user