[Python-checkins] python/dist/src/Modules _tkinter.c,1.153,1.154

loewis@users.sourceforge.net loewis@users.sourceforge.net
Tue, 15 Apr 2003 13:33:23 -0700


Update of /cvsroot/python/python/dist/src/Modules
In directory sc8-pr-cvs1:/tmp/cvs-serv7935

Modified Files:
	_tkinter.c 
Log Message:
Use object interface for global vars. Fixes #721171.
Also move complete processing of get/set/delvar calls to target thread.


Index: _tkinter.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Modules/_tkinter.c,v
retrieving revision 1.153
retrieving revision 1.154
diff -C2 -d -r1.153 -r1.154
*** _tkinter.c	30 Mar 2003 08:44:58 -0000	1.153
--- _tkinter.c	15 Apr 2003 20:33:20 -0000	1.154
***************
*** 1450,1504 ****
  TCL_DECLARE_MUTEX(var_mutex)
  
! typedef CONST84_RETURN char* (*EventFunc1)(Tcl_Interp*, CONST char*, int);
! typedef CONST84_RETURN char* (*EventFunc2)(Tcl_Interp*, CONST char*, CONST char*, int);
! typedef CONST84_RETURN char* (*EventFunc3)(Tcl_Interp*, CONST char*, CONST char*, CONST char*, int);
  typedef struct VarEvent {
  	Tcl_Event ev; /* must be first */
! 	TkappObject *self;
! 	char* arg1;
! 	char* arg2;
! 	char* arg3;
  	int flags;
! 	EventFunc1 func1;
! 	EventFunc2 func2;
! 	EventFunc3 func3;
  	PyObject **res;
! 	PyObject **exc;
  	Tcl_Condition cond;
- 	int coderesult;
  } VarEvent;
  
! static const char*
  var_perform(VarEvent *ev)
  {
! 	if (!ev->arg2 && !ev->arg2)
! 		return ev->func1(ev->self->interp, ev->arg1, ev->flags);
! 	if (!ev->arg3)
! 		return ev->func2(ev->self->interp, ev->arg1,
! 				 ev->arg2, ev->flags);
! 	return ev->func3(ev->self->interp, ev->arg1, ev->arg2,
! 			 ev->arg3, ev->flags);
! }
! 
! static void
! var_fill_result(VarEvent *ev, const char* res)
! {
! 	if (ev->coderesult) {
! 		if ((int)res != TCL_ERROR) {
! 			Py_INCREF(Py_None);
! 			*(ev->res) = Py_None;
! 			return;
! 		}
! 	}
! 	else if (res) {
! 		*(ev->res) = PyString_FromString(res);
! 		return;
  	}
! 
! 	*(ev->res) = NULL;
! 	*(ev->exc) = PyObject_CallFunction(
! 		Tkinter_TclError, "s",
! 		Tcl_GetStringResult(ev->self->interp));
! 
  }
  
--- 1450,1479 ----
  TCL_DECLARE_MUTEX(var_mutex)
  
! typedef PyObject* (*EventFunc)(PyObject*, PyObject *args, int flags);
  typedef struct VarEvent {
  	Tcl_Event ev; /* must be first */
! 	PyObject *self;
! 	PyObject *args;
  	int flags;
! 	EventFunc func;
  	PyObject **res;
! 	PyObject **exc_type;
! 	PyObject **exc_val;
  	Tcl_Condition cond;
  } VarEvent;
  
! void
  var_perform(VarEvent *ev)
  {
! 	*(ev->res) = ev->func(ev->self, ev->args, ev->flags);
! 	if (!*(ev->res)) {
! 		PyObject *exc, *val, *tb;
! 		PyErr_Fetch(&exc, &val, &tb);
! 		PyErr_NormalizeException(&exc, &val, &tb);
! 		*(ev->exc_type) = exc;
! 		*(ev->exc_val) = val;
! 		Py_DECREF(tb);
  	}
! 		
  }
  
***************
*** 1506,1512 ****
  var_proc(VarEvent* ev, int flags)
  {
- 	const char *result = var_perform(ev);
  	ENTER_PYTHON
! 	var_fill_result(ev, result);
  	Tcl_MutexLock(&var_mutex);
  	Tcl_ConditionNotify(&ev->cond);
--- 1481,1486 ----
  var_proc(VarEvent* ev, int flags)
  {
  	ENTER_PYTHON
!         var_perform(ev);
  	Tcl_MutexLock(&var_mutex);
  	Tcl_ConditionNotify(&ev->cond);
***************
*** 1517,1582 ****
  
  static PyObject*
! var_invoke(PyObject *_self, char* arg1, char* arg2, char* arg3, int flags,
! 	   EventFunc1 func1, EventFunc2 func2, EventFunc3 func3,
! 	   int coderesult)
  {
- 	VarEvent _ev;
  	TkappObject *self = (TkappObject*)_self;
- 	VarEvent *ev = self->threaded ? 
- 		(VarEvent*)ckalloc(sizeof(VarEvent)) : &_ev;
- 	PyObject *res, *exc;
- 
- 	ev->self = self;
- 	ev->arg1 = arg1;
- 	ev->arg2 = arg2;
- 	ev->arg3 = arg3;
- 	ev->flags = flags;
- 	ev->func1 = func1;
- 	ev->func2 = func2;
- 	ev->func3 = func3;
- 	ev->coderesult = coderesult;
- 	ev->res = &res;
- 	ev->exc = &exc;
  #ifdef WITH_THREAD
  	if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
  		/* The current thread is not the interpreter thread.  Marshal
  		   the call to the interpreter thread, then wait for
  		   completion. */
- 
  		if (!WaitForMainloop(self))
  			return NULL;
  		ev->cond = NULL;
  		ev->ev.proc = (Tcl_EventProc*)var_proc;
  		Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->cond, &var_mutex);
  	}
- 	else 
  #endif
! 	{
! 		/* Tcl is not threaded, or this is the interpreter thread.  To
! 		   perform the call, we must hold the TCL lock. To receive the
! 		   results, we must also hold the Python lock. */
! 		const char *result;
! 		ENTER_TCL
! 		result = var_perform(ev);
! 		ENTER_OVERLAP
! 		var_fill_result(ev, result);
! 		LEAVE_OVERLAP_TCL
! 	}
! 	if (!res) {
! 		PyErr_SetObject(Tkinter_TclError, exc);
! 		return NULL;
! 	}
! 	return res;
! }
! 
! static PyObject*
! var_invoke2(PyObject *_self, char* arg1, char* arg2, char* arg3, int flags,
! 	   int (*func1)(Tcl_Interp*, CONST char*, int),
! 	   int (*func2)(Tcl_Interp*, CONST char*, CONST char*, int),
! 	   int (*func3)(Tcl_Interp*, CONST char*, CONST char*, CONST char*, int))
! {
! 	return var_invoke(_self, arg1, arg2, arg3, flags,
! 			  (EventFunc1)func1, (EventFunc2)func2,
! 			  (EventFunc3)func3, 1);
  }
  
--- 1491,1532 ----
  
  static PyObject*
! var_invoke(EventFunc func, PyObject *_self, PyObject *args, int flags)
  {
  	TkappObject *self = (TkappObject*)_self;
  #ifdef WITH_THREAD
  	if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
+ 		TkappObject *self = (TkappObject*)_self;
+ 		VarEvent *ev;
+ 		PyObject *res, *exc_type, *exc_val;
+ 		
  		/* The current thread is not the interpreter thread.  Marshal
  		   the call to the interpreter thread, then wait for
  		   completion. */
  		if (!WaitForMainloop(self))
  			return NULL;
+ 
+ 		ev = (VarEvent*)ckalloc(sizeof(VarEvent));
+ 
+ 		ev->self = _self;
+ 		ev->args = args;
+ 		ev->flags = flags;
+ 		ev->func = func;
+ 		ev->res = &res;
+ 		ev->exc_type = &exc_type;
+ 		ev->exc_val = &exc_val;
  		ev->cond = NULL;
  		ev->ev.proc = (Tcl_EventProc*)var_proc;
  		Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->cond, &var_mutex);
+ 		if (!res) {
+ 			PyErr_SetObject(exc_type, exc_val);
+ 			Py_DECREF(exc_type);
+ 			Py_DECREF(exc_val);
+ 			return NULL;
+ 		}
+ 		return res;
  	}
  #endif
!         /* Tcl is not threaded, or this is the interpreter thread. */
! 	return func(_self, args, flags);
  }
  
***************
*** 1584,1603 ****
  SetVar(PyObject *self, PyObject *args, int flags)
  {
! 	char *name1, *name2, *s;
! 	PyObject *res;
  	PyObject *newValue;
! 	PyObject *tmp;
  
- 	tmp = PyList_New(0);
- 	if (!tmp)
- 		return NULL;
- 	
  	if (PyArg_ParseTuple(args, "sO:setvar", &name1, &newValue)) {
! 		/* XXX Merge? */
! 		s = AsString(newValue, tmp);
! 		if (s == NULL)
  			return NULL;
! 		res = var_invoke(self, name1, s, NULL, flags,
! 				 NULL, Tcl_SetVar, NULL, 0);
  	}
  	else {
--- 1534,1558 ----
  SetVar(PyObject *self, PyObject *args, int flags)
  {
! 	char *name1, *name2;
  	PyObject *newValue;
! 	PyObject *res = NULL;
! 	Tcl_Obj *newval, *ok;
  
  	if (PyArg_ParseTuple(args, "sO:setvar", &name1, &newValue)) {
! 		/* XXX Acquire tcl lock??? */
! 		newval = AsObj(newValue);
! 		if (newval == NULL)
  			return NULL;
! 		ENTER_TCL
! 		ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, NULL, 
! 				   newval, flags);
! 		ENTER_OVERLAP
! 		if (!ok)
! 			Tkinter_Error(self);
! 		else {
! 			res = Py_None;
! 			Py_INCREF(res);
! 		}
! 		LEAVE_OVERLAP_TCL
  	}
  	else {
***************
*** 1605,1627 ****
  		if (PyArg_ParseTuple(args, "ssO:setvar",
  				     &name1, &name2, &newValue)) {
! 			s = AsString(newValue, tmp);
! 			if (s == NULL)
! 				return NULL;
! 			res = var_invoke(self, name1, name2, s, flags,
! 					 NULL, NULL, Tcl_SetVar2, 0);
  		}
  		else {
- 			Py_DECREF(tmp);
  			return NULL;
  		}
  	}
! 	Py_DECREF(tmp);
! 
! 	if (!res)
! 		return NULL;
! 
! 	Py_DECREF(res);
! 	Py_INCREF(Py_None);
! 	return Py_None;
  }
  
--- 1560,1581 ----
  		if (PyArg_ParseTuple(args, "ssO:setvar",
  				     &name1, &name2, &newValue)) {
! 			/* XXX must hold tcl lock already??? */
! 			newval = AsObj(newValue);
! 			ENTER_TCL
! 			ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags);
! 			ENTER_OVERLAP
! 			if (!ok)
! 				Tkinter_Error(self);
! 			else {
! 				res = Py_None;
! 				Py_INCREF(res);
! 			}
! 			LEAVE_OVERLAP_TCL
  		}
  		else {
  			return NULL;
  		}
  	}
! 	return res;
  }
  
***************
*** 1629,1633 ****
  Tkapp_SetVar(PyObject *self, PyObject *args)
  {
! 	return SetVar(self, args, TCL_LEAVE_ERR_MSG);
  }
  
--- 1583,1587 ----
  Tkapp_SetVar(PyObject *self, PyObject *args)
  {
! 	return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG);
  }
  
***************
*** 1635,1639 ****
  Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
  {
! 	return SetVar(self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
  }
  
--- 1589,1593 ----
  Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
  {
! 	return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
  }
  
***************
*** 1645,1654 ****
  	char *name1, *name2=NULL;
  	PyObject *res = NULL;
  
  	if (!PyArg_ParseTuple(args, "s|s:getvar", &name1, &name2))
  		return NULL;
  
! 	res = var_invoke(self, name1, name2, NULL, flags,
! 			 Tcl_GetVar, Tcl_GetVar2, NULL, 0);
  	return res;
  }
--- 1599,1612 ----
  	char *name1, *name2=NULL;
  	PyObject *res = NULL;
+ 	Tcl_Obj *tres;
  
  	if (!PyArg_ParseTuple(args, "s|s:getvar", &name1, &name2))
  		return NULL;
  
! 	ENTER_TCL
! 	tres = Tcl_GetVar2Ex(Tkapp_Interp(self), name1, name2, flags);
! 	ENTER_OVERLAP
! 	res = FromObj(self, tres);
! 	LEAVE_OVERLAP_TCL
  	return res;
  }
***************
*** 1657,1661 ****
  Tkapp_GetVar(PyObject *self, PyObject *args)
  {
! 	return GetVar(self, args, TCL_LEAVE_ERR_MSG);
  }
  
--- 1615,1619 ----
  Tkapp_GetVar(PyObject *self, PyObject *args)
  {
! 	return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG);
  }
  
***************
*** 1663,1667 ****
  Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
  {
! 	return GetVar(self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
  }
  
--- 1621,1625 ----
  Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
  {
! 	return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
  }
  
***************
*** 1672,1675 ****
--- 1630,1634 ----
  {
  	char *name1, *name2=NULL;
+ 	int code;
  	PyObject *res = NULL;
  
***************
*** 1677,1682 ****
  		return NULL;
  
! 	res = var_invoke2(self, name1, name2, NULL, flags,
! 			  Tcl_UnsetVar, Tcl_UnsetVar2, NULL);
  	return res;
  }
--- 1636,1649 ----
  		return NULL;
  
! 	ENTER_TCL
! 	code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
! 	ENTER_OVERLAP
! 	if (code == TCL_ERROR)
! 		res = Tkinter_Error(self);
! 	else {
! 		Py_INCREF(Py_None);
! 		res = Py_None;
! 	}
! 	LEAVE_OVERLAP_TCL
  	return res;
  }
***************
*** 1685,1689 ****
  Tkapp_UnsetVar(PyObject *self, PyObject *args)
  {
! 	return UnsetVar(self, args, TCL_LEAVE_ERR_MSG);
  }
  
--- 1652,1656 ----
  Tkapp_UnsetVar(PyObject *self, PyObject *args)
  {
! 	return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG);
  }
  
***************
*** 1691,1695 ****
  Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
  {
! 	return UnsetVar(self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
  }
  
--- 1658,1662 ----
  Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
  {
! 	return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
  }