⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 thread_symbian.h

📁 python s60 1.4.5版本的源代码
💻 H
字号:
/*
* ====================================================================
*  thread_symbian.h
*  
*  Basic thread support on Symbian OS.
*
* Copyright (c) 2005 Nokia Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* 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 <e32std.h>
#include <e32base.h>
#include <e32math.h>

#define KStackSize 0x10000
#define KHeapSize 300000

extern "C" void SPy_InitStdio();   // in Symbian\CSPyInterpreter.cpp

/*
 * Initialization.
 */

static void
PyThread__init_thread(void)
{
}

/*
 * Thread support.
 */

struct launchpad_args {
  TThreadFunction f;
  TAny* arg;
  TAny* globals;
};

class CPyThreadRoot : public CActive
{
 public:
  CPyThreadRoot(TThreadFunction& aFunc, TAny* aArg):
    CActive(EPriorityStandard),iFunc(aFunc),iArg(aArg)
    {
      CActiveScheduler::Add(this);
    }

  void Start() {
    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);
    CActiveScheduler::Start();
  }

 private:
  void DoCancel() {;}
  void RunL() {
    iFunc(iArg);
    CActiveScheduler::Stop();
  }

  TThreadFunction iFunc;
  TAny* iArg;
};

static TInt launchpad(TAny* p)
{
  TThreadFunction func = ((launchpad_args*)p)->f;
  TAny* arg = ((launchpad_args*)p)->arg;
  
  if (SPy_tls_initialize((SPy_Python_globals*)((launchpad_args*)p)->globals))
    User::Panic(_L("Python thread"), KErrNoMemory);

  PyMem_DEL(p);

  SPy_InitStdio();

  CTrapCleanup* cleanup_stack = CTrapCleanup::New();
  //  __UHEAP_MARK;

  TRAPD(error, {
    CActiveScheduler* as = new (ELeave) CActiveScheduler;
    CleanupStack::PushL(as);
    CActiveScheduler::Install(as);

    CPyThreadRoot* pytroot = new (ELeave) CPyThreadRoot(func, arg);
    CleanupStack::PushL(pytroot);

    pytroot->Start();

    CleanupStack::PopAndDestroy();
    CleanupStack::PopAndDestroy();
  });

  __ASSERT_ALWAYS(!error, User::Panic(_L("Python thread"), error));

  //  CloseSTDLIB();
  User::Free(ImpurePtr());
  delete cleanup_stack;
  SPy_tls_finalize(0);
  //  __UHEAP_MARKEND;
  RThread().Terminate(0);
  return 0; // dummy
}

void createUniqueString(TDes16& str)
{
  TBuf<4> name_prefix;
  TBuf<11> rand_string;
  TInt rand = Math::Random();
  if (rand < 0) rand *= -1;
  rand_string.Num(rand);
  name_prefix.Append(_L("Py_"));
  str.Append(name_prefix);
  str.Append(rand_string);
}

extern "C" {
DL_EXPORT(long)
PyThread_start_new_thread(void (*func)(void *), void *arg)
{
  int success = 0;
  SPy_Python_globals* pg = PYTHON_GLOBALS;

  launchpad_args* lp_arg = (launchpad_args*)PyMem_NEW(struct launchpad_args, 1);
  if (!lp_arg)
    return (-1);
  lp_arg->f = (TThreadFunction)func;
  lp_arg->arg = (TAny*)arg;
  lp_arg->globals = (TAny*)pg;

  RThread t;
  TBuf<16> thread_name;
  createUniqueString(thread_name);
  success = t.Create(thread_name, launchpad, KStackSize,
                     KMinHeapSize, KHeapSize, (TAny*)lp_arg);  
  
  if (success == -11) {
  	//KErrAlreadyExists=(-11)
    //lets try once more to create a unique thread name, 
    //perhaps randomizer was unlucky last time
    thread_name.Delete(0, (thread_name.Size()) / 2);
    createUniqueString(thread_name);
    success = t.Create(thread_name, launchpad, KStackSize,
                     KMinHeapSize, KHeapSize, (TAny*)lp_arg); 
  }
	if (success == 0) {
	  t.SetPriority(EPriorityLess);
	  t.Resume();
	  success = t.Id();	
  }
  else
    PyMem_DEL(lp_arg);
  
  t.Close();

  return ((success < 0) ? -1 : success);
}
} /* extern "C" */

class CPyThreadWait : public CActive
{
 public:
  CPyThreadWait(TInt aTid):CActive(EPriorityStandard),iTid(aTid) {
    CActiveScheduler::Add(this);
  }

  ~CPyThreadWait() {
    iThread.Close();
  }

  int Wait() {
    if (iThread.Open(iTid) == KErrNone) {
      iThread.Logon(iStatus);
      SetActive();
      Py_BEGIN_ALLOW_THREADS
#ifdef HAVE_ACTIVESCHEDULERWAIT   
      iWait.Start();
#else
      CActiveScheduler::Start();
#endif
      Py_END_ALLOW_THREADS
      return ((iStatus.Int() != KErrNoMemory) ? 0 : (-1));
    }
    else
      return (-1);
  }

 private:
  void DoCancel() {;}
  void RunL() {
#ifdef HAVE_ACTIVESCHEDULERWAIT
    iWait.AsyncStop();
#else
    CActiveScheduler::Stop();
#endif
  }
  
  TInt iTid;
  RThread iThread;
#ifdef HAVE_ACTIVESCHEDULERWAIT
  CActiveSchedulerWait iWait;
#endif
};

extern "C" {
DL_EXPORT(int)
PyThread_ao_waittid(long tid)
{
  CPyThreadWait* w = new CPyThreadWait(tid);
  
  if (w) {
    int error = w->Wait();
    delete w;
    return error;
  }
  else
    return (-1);
}

DL_EXPORT(long)
PyThread_get_thread_ident(void)
{
  return (TUint)(RThread().Id());
}

static
void do_PyThread_exit_thread(int no_cleanup)
{
  if (!initialized)
    if (no_cleanup)
      _exit(0);
    else
      exit(0);
  while (PYTHON_TLS->n_exitfuncs > 0)
    (PYTHON_TLS->exitfuncs[--(PYTHON_TLS->n_exitfuncs)])();
}


DL_EXPORT(void)
PyThread_exit_thread(void)
{
  do_PyThread_exit_thread(0);
}

DL_EXPORT(void)
PyThread__exit_thread(void)
{
  do_PyThread_exit_thread(1);
}

DL_EXPORT(int)
PyThread_AtExit(void (*func)(void))
{
  if ((PYTHON_GLOBALS->main_thread == 0) ||
      (PYTHON_GLOBALS->main_thread == PyThread_get_thread_ident()))
    return Py_AtExit(func);
  
  if (PYTHON_TLS->n_exitfuncs >= MAXTHREADEXITFUNCS)
    return -1;
  PYTHON_TLS->exitfuncs[PYTHON_TLS->n_exitfuncs++] = func;
  return 0;
}
} /* extern "C" */

/*
 * Lock support.
 */

class Symbian_lock {
public:
  Symbian_lock():lock_value(0) {;}
  ~Symbian_lock() {cs.Close(); wait_q.Close();}
  TInt init();
  RCriticalSection cs;
  RSemaphore wait_q;
  TInt lock_value;
};

TInt Symbian_lock::init()
{
  TInt error = cs.CreateLocal();
  if (error == KErrNone) {
    error = wait_q.CreateLocal(0);
    if (error != KErrNone)
      cs.Close();
  }
  
  return error;
}

extern "C" {
DL_EXPORT(PyThread_type_lock)
PyThread_allocate_lock(void)
{
  if (!initialized)
    PyThread_init_thread();
  Symbian_lock* lock = NULL;
  void* raw_mem_in_python_chunk = PyMem_Malloc(sizeof(Symbian_lock));
  if (raw_mem_in_python_chunk) {
    lock = new (raw_mem_in_python_chunk) Symbian_lock();
    if (lock->init() != KErrNone) {
      lock->~Symbian_lock();
      PyMem_Free(raw_mem_in_python_chunk);
      lock = NULL;
    }
  } 
  return (PyThread_type_lock) lock;
}

DL_EXPORT(void)
PyThread_free_lock(PyThread_type_lock lock)
{
  ((Symbian_lock*)lock)->~Symbian_lock();
  PyMem_Free((void*)lock);
}

DL_EXPORT(int)
PyThread_acquire_lock(PyThread_type_lock lock, int waitflag)
{
  int success;

  ((Symbian_lock*)lock)->cs.Wait();
  success = (((Symbian_lock*)lock)->lock_value == 0);
  if (success || waitflag)
    ((Symbian_lock*)lock)->lock_value++;
  ((Symbian_lock*)lock)->cs.Signal();

  if (!success && waitflag) {
    ((Symbian_lock*)lock)->wait_q.Wait();
    success = 1;
  }

  return success;
}

DL_EXPORT(void)
PyThread_release_lock(PyThread_type_lock lock)
{
  ((Symbian_lock*)lock)->cs.Wait();
  
  if (((Symbian_lock*)lock)->lock_value > 0) {
    ((Symbian_lock*)lock)->lock_value--;
    if (((Symbian_lock*)lock)->lock_value)
      ((Symbian_lock*)lock)->wait_q.Signal();
  }

  ((Symbian_lock*)lock)->cs.Signal();
}
} /* extern "C" */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -