📄 e32module.cpp
字号:
CActiveScheduler::Add(this);
}
void DoYield() {
iStatus = KRequestPending;
SetActive();
//iStatus = KErrNone; // Doing this will panic the 3.0 emulator with E32USER-CBase 46 "Stray signal".
TRequestStatus* pstatus = &iStatus;
RThread().RequestComplete(pstatus, 0);
#ifdef HAVE_ACTIVESCHEDULERWAIT
iWait.Start();
#else
CActiveScheduler::Start();
#endif
}
private:
void DoCancel() {;}
void RunL() {
#ifdef HAVE_ACTIVESCHEDULERWAIT
iWait.AsyncStop();
#else
CActiveScheduler::Stop();
#endif
}
#ifdef HAVE_ACTIVESCHEDULERWAIT
CActiveSchedulerWait iWait;
#endif
};
extern "C" PyObject *
e32_ao_yield(PyObject* /*self*/)
{
CE32AoYield* y = new CE32AoYield();
if (!y)
return PyErr_NoMemory();
Py_BEGIN_ALLOW_THREADS
y->DoYield();
delete y;
Py_END_ALLOW_THREADS
Py_INCREF(Py_None);
return Py_None;
}
/*
*
* Implementation of e32.ao_sleep
*
*/
class CE32AoSleep : public CActive
{
public:
CE32AoSleep(PyObject* aCb=0):CActive(EPriorityStandard) {
iCb = aCb;
Py_XINCREF(iCb);
}
~CE32AoSleep() {
Cancel();
iTimer.Close();
Py_XDECREF(iCb);
}
TInt Construct() {
TInt error = iTimer.CreateLocal();
if (error == KErrNone)
CActiveScheduler::Add(this);
return error;
}
void DoSleep(TReal aDelay /*time in seconds*/) {
iTimeMultiplier = (TInt)(aDelay / MAX_TIME);
TReal timeLeft = aDelay - (MAX_TIME * iTimeMultiplier);
StartTimer(timeLeft);
if (!iCb){
Py_BEGIN_ALLOW_THREADS
#ifdef HAVE_ACTIVESCHEDULERWAIT
iWait.Start();
#else
CActiveScheduler::Start();
#endif
Py_END_ALLOW_THREADS
}
}
private:
void DoCancel() {
iTimer.Cancel();
}
void RunL() {
if (iTimeMultiplier>0) {
StartTimer(MAX_TIME);
iTimeMultiplier--;
}
else if (!iCb) {
#ifdef HAVE_ACTIVESCHEDULERWAIT
iWait.AsyncStop();
#else
CActiveScheduler::Stop();
#endif
delete this;
}
else {
PyEval_RestoreThread(PYTHON_TLS->thread_state);
PyObject* tmp_r = NULL;
tmp_r = PyEval_CallObject(iCb, NULL);
Py_XDECREF(tmp_r);
if (PyErr_Occurred())
PyErr_Print();
PyEval_SaveThread();
delete this;
}
}
void StartTimer(TReal aDelay) {
TTimeIntervalMicroSeconds32 delay;
#ifndef EKA2
delay = TTimeIntervalMicroSeconds32(TInt64(aDelay*1000*1000).GetTInt());
#else
delay = TTimeIntervalMicroSeconds32(TInt64(aDelay*1000*1000));
#endif
iTimer.After(iStatus, delay);
SetActive();
}
RTimer iTimer;
TInt iTimeMultiplier;
#ifdef HAVE_ACTIVESCHEDULERWAIT
CActiveSchedulerWait iWait;
#endif
PyObject* iCb;
};
extern "C" PyObject *
e32_ao_sleep(PyObject* /*self*/, PyObject* args)
{
TReal d;
PyObject* c=NULL;
if (!PyArg_ParseTuple(args, "d|O", &d, &c))
return NULL;
if (c && !PyCallable_Check(c)) {
PyErr_SetString(PyExc_TypeError, "callable expected for 2nd argument");
return NULL;
}
if (d < 0) {
PyErr_SetString(PyExc_RuntimeError, "negative number not allowed");
return NULL;
}
CE32AoSleep* s = new CE32AoSleep(c);
if (!s)
return PyErr_NoMemory();
TInt error = s->Construct();
if (error != KErrNone) {
delete s;
return SPyErr_SetFromSymbianOSErr(error);
}
s->DoSleep(d);
Py_INCREF(Py_None);
return Py_None;
}
/*
*
* Implementation of e32.Ao_timer
*
*/
#define Ao_timer_type (PYTHON_GLOBALS->t_Ao_timer)
#ifndef EKA2
class Ao_timer : public CActive {
#else
NONSHARABLE_CLASS(Ao_timer) : public CActive {
#endif
public:
Ao_timer();
void After(TTimeIntervalMicroSeconds32 aSleep, PyObject* aCb);
TInt Construct();
~Ao_timer();
private:
void RunL();
void DoCancel();
RTimer iTimer;
PyObject* iCb;
#ifdef HAVE_ACTIVESCHEDULERWAIT
CActiveSchedulerWait iWait;
#endif
};
Ao_timer::Ao_timer():CActive(EPriorityStandard) {;}
void Ao_timer::After(TTimeIntervalMicroSeconds32 aDelay, PyObject* aCb=0)
{
iCb = aCb;
Py_XINCREF(iCb);
iTimer.After(iStatus, aDelay);
SetActive();
if (!iCb) {
Py_BEGIN_ALLOW_THREADS
#ifdef HAVE_ACTIVESCHEDULERWAIT
iWait.Start();
#else
CActiveScheduler::Start();
#endif
Py_END_ALLOW_THREADS
}
}
TInt Ao_timer::Construct()
{
TInt error = iTimer.CreateLocal();
if (error == KErrNone)
CActiveScheduler::Add(this);
return error;
}
Ao_timer::~Ao_timer()
{
Cancel();
iTimer.Close();
Py_XDECREF(iCb);
}
void Ao_timer::RunL()
{
if (!iCb) {
#ifdef HAVE_ACTIVESCHEDULERWAIT
iWait.AsyncStop();
#else
CActiveScheduler::Stop();
#endif
}
else {
PyEval_RestoreThread(PYTHON_TLS->thread_state);
PyObject* tmp_r = NULL;
tmp_r = PyEval_CallObject(iCb, NULL);
Py_XDECREF(tmp_r);
if (PyErr_Occurred())
PyErr_Print();
PyEval_SaveThread();
}
}
void Ao_timer::DoCancel()
{
iTimer.Cancel();
}
struct Ao_timer_object {
PyObject_VAR_HEAD
Ao_timer* ob_data;
};
extern "C" PyObject *
new_e32_ao_timer_object(PyObject* /*self*/, PyObject /**args*/)
{
if (!CActiveScheduler::Current()) {
PyErr_SetString(PyExc_AssertionError, "no ao scheduler");
return NULL;
}
Ao_timer_object *op = PyObject_New(Ao_timer_object, &Ao_timer_type);
if (op == NULL)
return PyErr_NoMemory();
op->ob_data = new Ao_timer();
if (op->ob_data == NULL) {
PyObject_Del(op);
return PyErr_NoMemory();
}
TInt error = op->ob_data->Construct();
if (error != KErrNone) {
PyObject_Del(op);
return SPyErr_SetFromSymbianOSErr(error);
}
return (PyObject *) op;
}
extern "C" PyObject *
ao_timer_after(Ao_timer_object *self, PyObject* args)
{
TReal d;
PyObject* c=NULL;
if (!PyArg_ParseTuple(args, "d|O", &d, &c))
return NULL;
if (c && !PyCallable_Check(c)) {
PyErr_SetString(PyExc_TypeError, "callable expected for 2nd argument");
return NULL;
}
if(self->ob_data->IsActive()) {
PyErr_SetString(PyExc_RuntimeError, "Timer pending - cancel first");
return NULL;
}
if (d < 0) {
PyErr_SetString(PyExc_RuntimeError, "negative number not allowed");
return NULL;
}
#ifndef EKA2
self->ob_data->After(TTimeIntervalMicroSeconds32(TInt64(d*1000*1000).GetTInt()), c);
#else
self->ob_data->After(TTimeIntervalMicroSeconds32(TInt64(d*1000*1000)), c);
#endif /*EKA2*/
Py_INCREF(Py_None);
return Py_None;
}
extern "C" PyObject *
ao_timer_cancel(Ao_timer_object *self, PyObject* /*args*/)
{
self->ob_data->Cancel();
Py_INCREF(Py_None);
return Py_None;
}
extern "C" {
static void
ao_timer_dealloc(Ao_timer_object *op)
{
delete op->ob_data;
op->ob_data = NULL;
PyObject_Del(op);
}
static const PyMethodDef ao_timer_methods[] = {
{"after", (PyCFunction)ao_timer_after, METH_VARARGS},
{"cancel", (PyCFunction)ao_timer_cancel, METH_NOARGS},
{NULL, NULL} /* sentinel */
};
static PyObject *
ao_timer_getattr(Ao_timer_object *p, char *name)
{
return Py_FindMethod((PyMethodDef*)ao_timer_methods,
(PyObject *)p, name);
}
static const PyTypeObject c_Ao_timer_type = {
PyObject_HEAD_INIT(NULL)
0,
"e32.Ao_timer",
sizeof(Ao_timer_object),
0,
/* methods */
(destructor)ao_timer_dealloc, /* tp_dealloc */
0, /* tp_print */
(getattrfunc)ao_timer_getattr, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
0, /* tp_repr */
0, /* tp_as _number*/
0, /* tp_as _sequence*/
0, /* tp_as _mapping*/
0, /* tp_hash */
};
} /* extern "C" */
/*
*
* Implementation of e32.ao_callgate
*
*/
#define Ao_callgate_type ((PYTHON_GLOBALS->tobj).t_Ao_callgate)
struct Ao_callgate_call_item {
PyObject* args;
PyObject* kwargs;
Ao_callgate_call_item* next;
};
class Ao_callgate;
struct Ao_callgate_object {
PyObject_VAR_HEAD
Ao_callgate* ob_data;
unsigned int ob_tid;
Ao_callgate_call_item ob_args;
};
#ifndef EKA2
class Ao_callgate : public CActive {
#else
NONSHARABLE_CLASS(Ao_callgate) : public CActive {
#endif
public:
Ao_callgate(Ao_callgate_object* aOb, PyObject* aCb, TInt aTid);
~Ao_callgate() {
Cancel();
Py_DECREF(iCb);
}
TInt Signal(TInt aStatus=KErrNone);
private:
void RunL();
void DoCancel() {
Signal(KErrCancel);
}
TRequestStatus* iPst;
PyObject* iCb;
Ao_callgate_object* iOb;
TInt iTid;
};
Ao_callgate::Ao_callgate(Ao_callgate_object* aOb, PyObject* aCb, TInt aTid):
CActive(0),iOb(aOb),iTid(aTid)
{
iCb = aCb;
Py_INCREF(iCb);
CActiveScheduler::Add(this);
iStatus = KRequestPending;
iPst = &iStatus;
SetActive();
}
TInt Ao_callgate::Signal(TInt aReason)
{
RThread t;
TInt error = t.Open(iTid);
if (error == KErrNone) {
/* Check for this here, since this check crashes if the thread where the callgate was has finished already. */
if (iStatus != KRequestPending)
return KErrNone;
t.RequestComplete(iPst, aReason);
t.Close();
}
return error;
}
void Ao_callgate::RunL()
{
PyEval_RestoreThread(PYTHON_TLS->thread_state);
Ao_callgate_call_item* p = iOb->ob_args.next;
iOb->ob_args.next = NULL;
int lastReferenceGone = 0;
while (p) {
PyObject* tmp_r = NULL;
tmp_r = PyEval_CallObjectWithKeywords(iCb, p->args, p->kwargs);
Py_XDECREF(tmp_r);
if (PyErr_Occurred())
PyErr_Print();
Ao_callgate_call_item* tmp = p->next;
Py_XDECREF(p->args);
Py_XDECREF(p->kwargs);
PyMem_Free(p);
p = tmp;
lastReferenceGone=(iOb->ob_refcnt == 1);
/* Note: If refcount is 1, this object is destroyed right now!
* There shouldn't be any calls in the queue after this. */
Py_DECREF(iOb);
}
PyEval_SaveThread();
if (lastReferenceGone) {
/* If the last reference was lost above, then the object has been freed already, and we
* must not go poking around in the deallocated memory anymore. */
return;
}
iStatus = KRequestPending;
iPst = &iStatus;
SetActive();
}
extern "C" PyObject *
e32_ao_callgate(PyObject* /*self*/, PyObject* args)
{
if (!CActiveScheduler::Current()) {
PyErr_SetString(PyExc_AssertionError, "no ao scheduler");
return NULL;
}
PyObject* c;
if (!PyArg_ParseTuple(args, "O", &c))
return NULL;
if (!PyCallable_Check(c)) {
PyErr_SetString(PyExc_TypeError, "callable expected");
return NULL;
}
Ao_callgate_object *op = PyObject_New(Ao_callgate_object,
&Ao_callgate_type);
if (op == NULL)
return PyErr_NoMemory();
op->ob_args.args = NULL;
op->ob_args.kwargs = NULL;
op->ob_args.next = NULL;
op->ob_tid = RThread().Id();
if (!(op->ob_data = new Ao_callgate(op, c, op->ob_tid))) {
PyObject_Del(op);
return PyErr_NoMemory();
}
return (PyObject *) op;
}
extern "C" PyObject *
ao_cg_call(PyObject* self, PyObject* args, PyObject* kwargs)
{
Ao_callgate_object *op = (Ao_callgate_object*)self;
Ao_callgate_call_item* n =
(Ao_callgate_call_item*)PyMem_Malloc(sizeof(Ao_callgate_call_item));
if (!n)
return PyErr_NoMemory();
n->args = args;
Py_XINCREF(args);
n->kwargs = kwargs;
Py_XINCREF(kwargs);
n->next = NULL;
Ao_callgate_call_item* p = &(op->ob_args);
while (p->next) p = p->next;
p->next = n;
Py_INCREF(op);
TInt error = op->ob_data->Signal();
if (error != KErrNone) {
p->next = NULL;
Py_DECREF(op);
Py_XDECREF(n->args);
Py_XDECREF(n->kwargs);
PyMem_Free(n);
}
RETURN_ERROR_OR_PYNONE(error);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -