Added support for asynchronous execution from the script.

git-svn-id: http://voip.null.ro/svn/yate@5143 acf43c95-373e-0410-b603-e72c3f656dc1
This commit is contained in:
paulc 2012-06-21 13:26:11 +00:00
parent dad389aee0
commit 89ee4322b7
3 changed files with 94 additions and 16 deletions

View File

@ -1914,8 +1914,6 @@ bool JsCode::evalList(ObjList& stack, GenObject* context) const
XDebug(this,DebugInfo,"JsCode::evalList(%p,%p)",&stack,context);
JsRunner* runner = static_cast<JsRunner*>(context);
const ObjList* (& opcode) = runner->m_opcode;
if (!opcode)
opcode = m_opcodes.skipNull();
while (opcode) {
const ExpOperation* o = static_cast<const ExpOperation*>(opcode->get());
opcode = opcode->skipNext();
@ -2072,7 +2070,7 @@ ScriptRun* JsCode::createRunner(ScriptContext* context)
ScriptRun::Status JsRunner::reset()
{
Status s = ScriptRun::reset();
m_opcode = 0;
m_opcode = code() ? static_cast<const JsCode*>(code())->m_opcodes.skipNull() : 0;
m_index = 0;
return s;
}
@ -2303,5 +2301,4 @@ ExpOperation* JsParser::nullClone()
return s_null.ExpOperation::clone();
}
/* vi: set ts=8 sw=4 sts=4 noet: */

View File

@ -276,18 +276,26 @@ ScriptRun::Status ScriptRun::resume()
// Execute one or more instructions of code from where it was left
ScriptRun::Status ScriptRun::execute()
{
Lock mylock(this);
if (Incomplete != m_state)
return m_state;
m_state = Running;
mylock.drop();
Status st = resume();
if (Running == st)
st = Incomplete;
lock();
if (Running == m_state)
m_state = st;
unlock();
Status st;
do {
Lock mylock(this);
if (Incomplete != m_state)
return m_state;
m_state = Running;
mylock.drop();
st = resume();
if (Running == st)
st = Incomplete;
lock();
if (Running == m_state)
m_state = st;
ListIterator iter(m_async);
unlock();
while (ScriptAsync* op = static_cast<ScriptAsync*>(iter.get())) {
if (op->run())
m_async.remove(op);
}
} while (Running == st);
return st;
}
@ -335,4 +343,22 @@ bool ScriptRun::runAssign(const ExpOperation& oper, GenObject* context)
return ctxt->runAssign(noStack,oper,context);
}
// Insert an asynchronous operation
bool ScriptRun::insertAsync(ScriptAsync* oper)
{
if (!oper)
return false;
m_async.insert(oper);
return true;
}
// Append an asynchronous operation
bool ScriptRun::appendAsync(ScriptAsync* oper)
{
if (!oper)
return false;
m_async.append(oper);
return true;
}
/* vi: set ts=8 sw=4 sts=4 noet: */

View File

@ -1324,6 +1324,46 @@ public:
*/
inline ScriptRun* runner()
{ return m_runner; }
private:
ScriptRun* m_runner;
};
/**
* Operation that is to be executed by the script runtime before current operation
* @short Asynchronous execution support
*/
class YSCRIPT_API ScriptAsync : public GenObject
{
YCLASS(ScriptAsync,GenObject)
public:
/**
* Constructor
* @param owner The script running instance that will own this operation
*/
ScriptAsync(ScriptRun* owner)
: m_runner(owner)
{ }
/**
* Destructor
*/
virtual ~ScriptAsync()
{ }
/**
* Retrieve the script running instance that owns this stack
* @return Pointer to owner script instance
*/
inline ScriptRun* runner()
{ return m_runner; }
/**
* Execute the aynchronous operation with context unlocked if the script is paused
* @return True if the operation should be removed (was one-shot)
*/
virtual bool run() = 0;
private:
ScriptRun* m_runner;
};
@ -1458,6 +1498,20 @@ public:
*/
virtual bool callable(const String& name);
/**
* Insert an asynchronous operation to be executed
* @param oper Operation to be inserted, will be owned by the runtime instance
* @return True if the operation was added
*/
virtual bool insertAsync(ScriptAsync* oper);
/**
* Append an asynchronous operation to be executed
* @param oper Operation to be appended, will be owned by the runtime instance
* @return True if the operation was added
*/
virtual bool appendAsync(ScriptAsync* oper);
/**
* Try to assign a value to a single field in the script context
* @param oper Field to assign to, contains the field name and new value
@ -1478,6 +1532,7 @@ private:
ScriptContext* m_context;
Status m_state;
ObjList m_stack;
ObjList m_async;
};
/**