mirror of
https://github.com/gnustep/libs-base.git
synced 2025-04-23 17:10:48 +00:00
Add @synchronize support. The synchronize.m file will be committed to GCC as soon as Andrew P. looks at it and it is tested fully. I am committing it here for cases where the compiler can parse @synchronize, but doesn't have the necessary functions in the runtime.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@26869 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
6f85f5292c
commit
3d16dda1a5
7 changed files with 7641 additions and 7033 deletions
12
ChangeLog
12
ChangeLog
|
@ -1,3 +1,15 @@
|
|||
2008-09-23 20:31-EDT Gregory John Casamento <greg_casamento@yahoo.com>
|
||||
|
||||
* config.mak.in: Added reference to HAVE_OBJC_SYNC_ENTER
|
||||
* configure: Recompiled script
|
||||
* configure.ac: Changed configure to check for objc_sync_enter
|
||||
function.
|
||||
* Headers/Additions/GNUstepBase/config.h.in: Added #define here for
|
||||
HAVE_OBJC_SYNC_ENTER
|
||||
* Source/GNUmakefile: Added check for the value, if no, then compile
|
||||
synchronization.m
|
||||
* Source/synchronization.m: Implementation for @synchronize support.
|
||||
|
||||
2008-09-23 Richard Frith-Macdonald <rfm@gnu.org>
|
||||
|
||||
* Source/NSThread.m: add a couple of checks to ensure correct
|
||||
|
|
|
@ -652,6 +652,10 @@
|
|||
first (like Motorola and SPARC, unlike Intel and VAX). */
|
||||
#undef WORDS_BIGENDIAN
|
||||
|
||||
/* Define to 1 if the libobjc library contains objc_sync_enter and supports
|
||||
the @synchronize directive. If not, then we'll provide it. */
|
||||
#undef HAVE_OBJC_SYNC_ENTER
|
||||
|
||||
/* Define to `__inline__' or `__inline' if that's what the C compiler
|
||||
calls it, or to nothing if 'inline' is not supported under any name. */
|
||||
#ifndef __cplusplus
|
||||
|
|
|
@ -109,6 +109,11 @@ ifeq ($(GNUSTEP_TARGET_OS), mingw32)
|
|||
GNU_MFILES += libgnustep-base-entry.m
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_OBJC_SYNC_ENTER), no)
|
||||
GNU_MFILES += synchronization.m
|
||||
endif
|
||||
|
||||
|
||||
GNU_OTHER_SRCFILES = \
|
||||
win32-entry.m \
|
||||
win32-def.top \
|
||||
|
|
244
Source/synchronization.m
Normal file
244
Source/synchronization.m
Normal file
|
@ -0,0 +1,244 @@
|
|||
/*
|
||||
The implementation of synchronization primitives for Objective-C.
|
||||
Copyright (C) 2008 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
Gregory Casamento <greg.casamento@gmail.com>
|
||||
|
||||
GCC is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 2, or (at your option) any
|
||||
later version.
|
||||
|
||||
GCC is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GCC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
As a special exception, if you link this library with files compiled
|
||||
with GCC to produce an executable, this does not cause the resulting
|
||||
executable to be covered by the GNU General Public License. This
|
||||
exception does not however invalidate any other reasons why the
|
||||
executable file might be covered by the GNU General Public License.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "objc/objc.h"
|
||||
#include "objc/objc-api.h"
|
||||
#include "objc/thr.h"
|
||||
|
||||
/*
|
||||
* Node structure...
|
||||
*/
|
||||
typedef struct lock_node {
|
||||
id obj;
|
||||
objc_mutex_t lock;
|
||||
struct lock_node *next;
|
||||
struct lock_node *prev;
|
||||
} lock_node_t;
|
||||
|
||||
/*
|
||||
* Return types for the locks...
|
||||
*/
|
||||
typedef enum {
|
||||
OBJC_SYNC_SUCCESS = 0,
|
||||
OBJC_SYNC_NOT_OWNING_THREAD_ERROR = -1,
|
||||
OBJC_SYNC_TIMED_OUT = -2,
|
||||
OBJC_SYNC_NOT_INITIALIZED = -3
|
||||
} sync_return_t;
|
||||
|
||||
static lock_node_t *lock_list = NULL;
|
||||
static objc_mutex_t table_lock = NULL;
|
||||
|
||||
/**
|
||||
* Initialize the table lock.
|
||||
*/
|
||||
static void sync_lock_init()
|
||||
{
|
||||
if(table_lock == NULL)
|
||||
{
|
||||
table_lock = objc_mutex_allocate();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the node in the list.
|
||||
*/
|
||||
lock_node_t* objc_sync_find_node(id obj)
|
||||
{
|
||||
lock_node_t *current = NULL;
|
||||
|
||||
if(lock_list != NULL)
|
||||
{
|
||||
// iterate over the list looking for the end...
|
||||
while(current != NULL)
|
||||
{
|
||||
// if the current object is the one, breal and
|
||||
// return that node.
|
||||
if(current->obj == obj)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// get the next one...
|
||||
current = current->next;
|
||||
}
|
||||
}
|
||||
return current;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a node for the object, if one doesn't already exist.
|
||||
*/
|
||||
lock_node_t* objc_sync_add_node(id obj)
|
||||
{
|
||||
lock_node_t *current = NULL;
|
||||
|
||||
// get the lock...
|
||||
sync_lock_init();
|
||||
|
||||
// restrict access to the table....
|
||||
objc_mutex_lock(table_lock);
|
||||
|
||||
// if the list hasn't been initialized, initialize it.
|
||||
if(lock_list == NULL)
|
||||
{
|
||||
// instantiate the new node and set the list...
|
||||
lock_list = malloc(sizeof(lock_node_t));
|
||||
|
||||
// set the current node to the last in the list...
|
||||
current = lock_list;
|
||||
|
||||
// set next and prev...
|
||||
current->prev = NULL;
|
||||
current->next = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
lock_node_t *new_node = NULL;
|
||||
current = lock_list;
|
||||
|
||||
// look for the end of the list.
|
||||
while(current->next)
|
||||
{
|
||||
current = current->next;
|
||||
}
|
||||
|
||||
// instantiate the new node...
|
||||
new_node = malloc(sizeof(lock_node_t));
|
||||
|
||||
if(new_node != NULL)
|
||||
{
|
||||
// set next and prev...
|
||||
current->next = new_node;
|
||||
new_node->prev = current;
|
||||
new_node->next = NULL;
|
||||
|
||||
// set the current node to the last in the list...
|
||||
current = new_node;
|
||||
}
|
||||
}
|
||||
|
||||
if(current != NULL)
|
||||
{
|
||||
// add the object and it's lock
|
||||
current->obj = obj;
|
||||
current->lock = objc_mutex_allocate();
|
||||
}
|
||||
|
||||
// release access to the table...
|
||||
objc_mutex_unlock(table_lock);
|
||||
|
||||
return current;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the node for the object if one does exist.
|
||||
*/
|
||||
lock_node_t* objc_sync_remove_node(id obj)
|
||||
{
|
||||
lock_node_t *curr = NULL;
|
||||
|
||||
// find the node...
|
||||
curr = objc_sync_find_node(obj);
|
||||
|
||||
// if the node is not null, proceed...
|
||||
if(curr != NULL)
|
||||
{
|
||||
// skip the current node in
|
||||
// the list and remove it from the
|
||||
// prev and next nodes.
|
||||
lock_node_t *prev = NULL;
|
||||
lock_node_t *next = NULL;
|
||||
|
||||
prev = curr->prev;
|
||||
next = curr->next;
|
||||
|
||||
next->prev = prev;
|
||||
prev->next = next;
|
||||
}
|
||||
|
||||
// return the removed node...
|
||||
return curr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a lock for the object.
|
||||
*/
|
||||
int objc_sync_enter(id obj)
|
||||
{
|
||||
lock_node_t *node = NULL;
|
||||
int status = 0;
|
||||
|
||||
node = objc_sync_find_node(obj);
|
||||
if(node == NULL)
|
||||
{
|
||||
node = objc_sync_add_node(obj);
|
||||
if(node == NULL)
|
||||
{
|
||||
return OBJC_SYNC_NOT_INITIALIZED;
|
||||
}
|
||||
}
|
||||
|
||||
status = objc_mutex_lock(node->lock);
|
||||
if(status < 1)
|
||||
{
|
||||
return OBJC_SYNC_NOT_OWNING_THREAD_ERROR;
|
||||
}
|
||||
|
||||
return OBJC_SYNC_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a lock for the object.
|
||||
*/
|
||||
int objc_sync_exit(id obj)
|
||||
{
|
||||
lock_node_t *node = NULL;
|
||||
int status = 0;
|
||||
|
||||
node = objc_sync_remove_node(obj);
|
||||
if(node == NULL)
|
||||
{
|
||||
return OBJC_SYNC_NOT_INITIALIZED;
|
||||
}
|
||||
|
||||
status = objc_mutex_unlock(node->lock);
|
||||
if(status < 1)
|
||||
{
|
||||
return OBJC_SYNC_NOT_OWNING_THREAD_ERROR;
|
||||
}
|
||||
|
||||
// dealloc the node and return success.
|
||||
free(node);
|
||||
return OBJC_SYNC_SUCCESS;
|
||||
}
|
||||
|
|
@ -21,6 +21,7 @@ NX_CONST_STRING_CLASS=@NX_CONST_STRING_CLASS@
|
|||
HAVE_PTHREAD_H=@HAVE_PTHREAD_H@
|
||||
HAVE_INET_PTON=@HAVE_INET_PTON@
|
||||
HAVE_INET_NTOP=@HAVE_INET_NTOP@
|
||||
HAVE_OBJC_SYNC_ENTER=@HAVE_OBJC_SYNC_ENTER@
|
||||
|
||||
CONFIG_SYSTEM_INCL += @INCLUDE_FLAGS@
|
||||
ifeq ($(shared),yes)
|
||||
|
|
11
configure.ac
11
configure.ac
|
@ -1309,6 +1309,17 @@ AC_EGREP_HEADER(objc_get_uninstalled_dtable, objc/objc-api.h,
|
|||
LIBS="$saved_LIBS"
|
||||
CPPFLAGS="$saved_CPPFLAGS"
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
# Function needed by @synchronize directive
|
||||
#--------------------------------------------------------------------
|
||||
AC_CHECK_FUNCS(objc_sync_enter)
|
||||
|
||||
HAVE_OBJC_SYNC_ENTER=no
|
||||
if test $ac_cv_func_objc_sync_enter = yes ; then
|
||||
HAVE_OBJC_SYNC_ENTER=yes
|
||||
fi
|
||||
AC_SUBST(HAVE_OBJC_SYNC_ENTER)
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
# Generic settings needed by NSZone.m
|
||||
#--------------------------------------------------------------------
|
||||
|
|
Loading…
Reference in a new issue