PRIntervalTime
DOMStorageDBThread::TimeUntilFlush()
{
if (mFlushImmediately) {
return 0; // Do it now regardless the timeout.
}
static_assert(PR_INTERVAL_NO_TIMEOUT != 0,
"PR_INTERVAL_NO_TIMEOUT must be non-zero");
if (!mDirtyEpoch) {
return PR_INTERVAL_NO_TIMEOUT; // No pending task...
}
static const PRIntervalTime kMaxAge = PR_MillisecondsToInterval(FLUSHING_INTERVAL_MS);
PRIntervalTime now = PR_IntervalNow() | 1;
PRIntervalTime age = now - mDirtyEpoch;
if (age > kMaxAge) {
return 0; // It is time.
}
return kMaxAge - age; // Time left, this is used to sleep the monitor
}
static PRAlarmID *pr_getNextAlarm(PRAlarm *alarm, PRAlarmID *id)
{
/*
* Puts 'id' back into the sorted list iff it's not NULL.
* Removes the first element from the list and returns it (or NULL).
* List is "assumed" to be short.
*
* NB: Caller is providing locking
*/
PRCList *timer;
PRAlarmID *result = id;
PRIntervalTime now = PR_IntervalNow();
if (!PR_CLIST_IS_EMPTY(&alarm->timers))
{
if (id != NULL) /* have to put this id back in */
{
PRIntervalTime idDelta = now - id->nextNotify;
timer = alarm->timers.next;
do
{
result = (PRAlarmID*)timer;
if ((PRIntervalTime)(now - result->nextNotify) > idDelta)
{
PR_INSERT_BEFORE(&id->list, &alarm->timers);
break;
}
timer = timer->next;
} while (timer != &alarm->timers);
}
result = (PRAlarmID*)(timer = PR_LIST_HEAD(&alarm->timers));
PR_REMOVE_LINK(timer); /* remove it from the list */
}
return result;
} /* pr_getNextAlarm */
//.........这里部分代码省略.........
case NS_DID_PAINT: {
nsRefPtr<nsViewManager> rootVM = RootViewManager();
rootVM->CallDidPaintOnObserver();
break;
}
case NS_CREATE:
case NS_DESTROY:
case NS_SETZLEVEL:
/* Don't pass these events through. Passing them through
causes performance problems on pages with lots of views/frames
@see bug 112861 */
*aStatus = nsEventStatus_eConsumeNoDefault;
break;
case NS_DISPLAYCHANGED:
//Destroy the cached backbuffer to force a new backbuffer
//be constructed with the appropriate display depth.
//@see bugzilla bug 6061
*aStatus = nsEventStatus_eConsumeDoDefault;
break;
case NS_SYSCOLORCHANGED:
{
if (mPresShell) {
// Hold a refcount to the presshell. The continued existence of the observer will
// delay deletion of this view hierarchy should the event want to cause its
// destruction in, say, some JavaScript event handler.
nsCOMPtr<nsIPresShell> presShell = mPresShell;
presShell->HandleEvent(aView->GetFrame(), aEvent, false, aStatus);
}
}
break;
default:
{
if ((NS_IS_MOUSE_EVENT(aEvent) &&
// Ignore mouse events that we synthesize.
static_cast<nsMouseEvent*>(aEvent)->reason ==
nsMouseEvent::eReal &&
// Ignore mouse exit and enter (we'll get moves if the user
// is really moving the mouse) since we get them when we
// create and destroy widgets.
aEvent->message != NS_MOUSE_EXIT &&
aEvent->message != NS_MOUSE_ENTER) ||
NS_IS_KEY_EVENT(aEvent) ||
NS_IS_IME_EVENT(aEvent) ||
aEvent->message == NS_PLUGIN_INPUT_EVENT) {
gLastUserEventTime = PR_IntervalToMicroseconds(PR_IntervalNow());
}
if (aEvent->message == NS_DEACTIVATE) {
// if a window is deactivated, clear the mouse capture regardless
// of what is capturing
nsIPresShell::ClearMouseCapture(nsnull);
}
// Find the view whose coordinates system we're in.
nsIView* view = aView;
bool dispatchUsingCoordinates = NS_IsEventUsingCoordinates(aEvent);
if (dispatchUsingCoordinates) {
// Will dispatch using coordinates. Pretty bogus but it's consistent
// with what presshell does.
view = GetDisplayRootFor(view);
}
// If the view has no frame, look for a view that does.
nsIFrame* frame = view->GetFrame();
if (!frame &&
(dispatchUsingCoordinates || NS_IS_KEY_EVENT(aEvent) ||
NS_IS_IME_RELATED_EVENT(aEvent) ||
NS_IS_NON_RETARGETED_PLUGIN_EVENT(aEvent) ||
aEvent->message == NS_PLUGIN_ACTIVATE ||
aEvent->message == NS_PLUGIN_FOCUS)) {
while (view && !view->GetFrame()) {
view = view->GetParent();
}
if (view) {
frame = view->GetFrame();
}
}
if (nsnull != frame) {
// Hold a refcount to the presshell. The continued existence of the
// presshell will delay deletion of this view hierarchy should the event
// want to cause its destruction in, say, some JavaScript event handler.
nsCOMPtr<nsIPresShell> shell = view->GetViewManager()->GetPresShell();
if (shell) {
shell->HandleEvent(frame, aEvent, false, aStatus);
}
}
break;
}
}
return NS_OK;
}
void
mozTXTToHTMLConv::ScanHTML(nsString& aInString, PRUint32 whattodo, nsString &aOutString)
{
// some common variables we were recalculating
// every time inside the for loop...
PRInt32 lengthOfInString = aInString.Length();
const PRUnichar * uniBuffer = aInString.get();
#ifdef DEBUG_BenB_Perf
PRTime parsing_start = PR_IntervalNow();
#endif
// Look for simple entities not included in a tags and scan them.
/* Skip all tags ("<[...]>") and content in an a tag ("<a[...]</a>")
or in a tag ("<!--[...]-->").
Unescape the rest (text between tags) and pass it to ScanTXT. */
for (PRInt32 i = 0; i < lengthOfInString;)
{
if (aInString[i] == '<') // html tag
{
PRUint32 start = PRUint32(i);
if (nsCRT::ToLower((char)aInString[PRUint32(i) + 1]) == 'a')
// if a tag, skip until </a>
{
i = aInString.Find("</a>", true, i);
if (i == kNotFound)
i = lengthOfInString;
else
i += 4;
}
else if (aInString[PRUint32(i) + 1] == '!' && aInString[PRUint32(i) + 2] == '-' &&
aInString[PRUint32(i) + 3] == '-')
//if out-commended code, skip until -->
{
i = aInString.Find("-->", false, i);
if (i == kNotFound)
i = lengthOfInString;
else
i += 3;
}
else // just skip tag (attributes etc.)
{
i = aInString.FindChar('>', i);
if (i == kNotFound)
i = lengthOfInString;
else
i++;
}
aOutString.Append(&uniBuffer[start], PRUint32(i) - start);
}
else
{
PRUint32 start = PRUint32(i);
i = aInString.FindChar('<', i);
if (i == kNotFound)
i = lengthOfInString;
nsString tempString;
tempString.SetCapacity(PRUint32((PRUint32(i) - start) * growthRate));
UnescapeStr(uniBuffer, start, PRUint32(i) - start, tempString);
ScanTXT(tempString.get(), tempString.Length(), whattodo, aOutString);
}
}
#ifdef DEBUG_BenB_Perf
printf("ScanHTML time: %d ms\n", PR_IntervalToMilliseconds(PR_IntervalNow() - parsing_start));
#endif
}
/*
** Expire condition variable waits that are ready to expire. "now" is the current
** time.
*/
void _PR_ClockInterrupt(void)
{
PRThread *thread, *me = _PR_MD_CURRENT_THREAD();
_PRCPU *cpu = me->cpu;
PRIntervalTime elapsed, now;
PR_ASSERT(_PR_MD_GET_INTSOFF() != 0);
/* Figure out how much time elapsed since the last clock tick */
now = PR_IntervalNow();
elapsed = now - cpu->last_clock;
cpu->last_clock = now;
#ifndef XP_MAC
PR_LOG(_pr_clock_lm, PR_LOG_MAX,
("ExpireWaits: elapsed=%lld usec", elapsed));
#endif
while(1) {
_PR_SLEEPQ_LOCK(cpu);
if (_PR_SLEEPQ(cpu).next == &_PR_SLEEPQ(cpu)) {
_PR_SLEEPQ_UNLOCK(cpu);
break;
}
thread = _PR_THREAD_PTR(_PR_SLEEPQ(cpu).next);
PR_ASSERT(thread->cpu == cpu);
if (elapsed < thread->sleep) {
thread->sleep -= elapsed;
_PR_SLEEPQMAX(thread->cpu) -= elapsed;
_PR_SLEEPQ_UNLOCK(cpu);
break;
}
_PR_SLEEPQ_UNLOCK(cpu);
PR_ASSERT(!_PR_IS_NATIVE_THREAD(thread));
_PR_THREAD_LOCK(thread);
if (thread->cpu != cpu) {
/*
** The thread was switched to another CPU
** between the time we unlocked the sleep
** queue and the time we acquired the thread
** lock, so it is none of our business now.
*/
_PR_THREAD_UNLOCK(thread);
continue;
}
/*
** Consume this sleeper's amount of elapsed time from the elapsed
** time value. The next remaining piece of elapsed time will be
** available for the next sleeping thread's timer.
*/
_PR_SLEEPQ_LOCK(cpu);
PR_ASSERT(!(thread->flags & _PR_ON_PAUSEQ));
if (thread->flags & _PR_ON_SLEEPQ) {
_PR_DEL_SLEEPQ(thread, PR_FALSE);
elapsed -= thread->sleep;
_PR_SLEEPQ_UNLOCK(cpu);
} else {
/* Thread was already handled; Go get another one */
_PR_SLEEPQ_UNLOCK(cpu);
_PR_THREAD_UNLOCK(thread);
continue;
}
/* Notify the thread waiting on the condition variable */
if (thread->flags & _PR_SUSPENDING) {
PR_ASSERT((thread->state == _PR_IO_WAIT) ||
(thread->state == _PR_COND_WAIT));
/*
** Thread is suspended and its condition timeout
** expired. Transfer thread from sleepQ to suspendQ.
*/
thread->wait.cvar = NULL;
_PR_MISCQ_LOCK(cpu);
thread->state = _PR_SUSPENDED;
_PR_ADD_SUSPENDQ(thread, cpu);
_PR_MISCQ_UNLOCK(cpu);
} else {
if (thread->wait.cvar) {
PRThreadPriority pri;
/* Do work very similar to what _PR_NotifyThread does */
PR_ASSERT( !_PR_IS_NATIVE_THREAD(thread) );
/* Make thread runnable */
pri = thread->priority;
thread->state = _PR_RUNNABLE;
PR_ASSERT(!(thread->flags & _PR_IDLE_THREAD));
PR_ASSERT(thread->cpu == cpu);
_PR_RUNQ_LOCK(cpu);
_PR_ADD_RUNQ(thread, cpu, pri);
//.........这里部分代码省略.........
/*
* io worker thread function
*/
static void io_wstart(void *arg)
{
PRThreadPool *tp = (PRThreadPool *) arg;
int pollfd_cnt, pollfds_used;
int rv;
PRCList *qp, *nextqp;
PRPollDesc *pollfds;
PRJob **polljobs;
int poll_timeout;
PRIntervalTime now;
/*
* scan io_jobq
* construct poll list
* call PR_Poll
* for all fds, for which poll returns true, move the job to
* jobq and wakeup worker thread.
*/
while (!tp->shutdown) {
PRJob *jobp;
pollfd_cnt = tp->ioq.cnt + 10;
if (pollfd_cnt > tp->ioq.npollfds) {
/*
* re-allocate pollfd array if the current one is not large
* enough
*/
if (NULL != tp->ioq.pollfds)
PR_Free(tp->ioq.pollfds);
tp->ioq.pollfds = (PRPollDesc *) PR_Malloc(pollfd_cnt *
(sizeof(PRPollDesc) + sizeof(PRJob *)));
PR_ASSERT(NULL != tp->ioq.pollfds);
/*
* array of pollfds
*/
pollfds = tp->ioq.pollfds;
tp->ioq.polljobs = (PRJob **) (&tp->ioq.pollfds[pollfd_cnt]);
/*
* parallel array of jobs
*/
polljobs = tp->ioq.polljobs;
tp->ioq.npollfds = pollfd_cnt;
}
pollfds_used = 0;
/*
* add the notify fd; used for unblocking io thread(s)
*/
pollfds[pollfds_used].fd = tp->ioq.notify_fd;
pollfds[pollfds_used].in_flags = PR_POLL_READ;
pollfds[pollfds_used].out_flags = 0;
polljobs[pollfds_used] = NULL;
pollfds_used++;
/*
* fill in the pollfd array
*/
PR_Lock(tp->ioq.lock);
for (qp = tp->ioq.list.next; qp != &tp->ioq.list; qp = nextqp) {
nextqp = qp->next;
jobp = JOB_LINKS_PTR(qp);
if (jobp->cancel_io) {
CANCEL_IO_JOB(jobp);
continue;
}
if (pollfds_used == (pollfd_cnt))
break;
pollfds[pollfds_used].fd = jobp->iod->socket;
pollfds[pollfds_used].in_flags = jobp->io_poll_flags;
pollfds[pollfds_used].out_flags = 0;
polljobs[pollfds_used] = jobp;
pollfds_used++;
}
if (!PR_CLIST_IS_EMPTY(&tp->ioq.list)) {
qp = tp->ioq.list.next;
jobp = JOB_LINKS_PTR(qp);
if (PR_INTERVAL_NO_TIMEOUT == jobp->timeout)
poll_timeout = PR_INTERVAL_NO_TIMEOUT;
else if (PR_INTERVAL_NO_WAIT == jobp->timeout)
poll_timeout = PR_INTERVAL_NO_WAIT;
else {
poll_timeout = jobp->absolute - PR_IntervalNow();
if (poll_timeout <= 0) /* already timed out */
poll_timeout = PR_INTERVAL_NO_WAIT;
}
} else {
poll_timeout = PR_INTERVAL_NO_TIMEOUT;
}
PR_Unlock(tp->ioq.lock);
/*
* XXXX
* should retry if more jobs have been added to the queue?
*
*/
PR_ASSERT(pollfds_used <= pollfd_cnt);
//.........这里部分代码省略.........
开发者ID:Akesure,项目名称:jxcore,代码行数:101,代码来源:prtpool.c
示例14: Server
static void PR_CALLBACK Server(void *arg)
{
PRStatus rv;
PRNetAddr serverAddress;
PRThread *me = PR_GetCurrentThread();
CSServer_t *server = (CSServer_t*)arg;
PRSocketOptionData sockOpt;
server->listener = PR_Socket(domain, SOCK_STREAM, protocol);
sockOpt.option = PR_SockOpt_Reuseaddr;
sockOpt.value.reuse_addr = PR_TRUE;
rv = PR_SetSocketOption(server->listener, &sockOpt);
TEST_ASSERT(PR_SUCCESS == rv);
memset(&serverAddress, 0, sizeof(serverAddress));
if (PR_AF_INET6 != domain)
rv = PR_InitializeNetAddr(PR_IpAddrAny, DEFAULT_PORT, &serverAddress);
else
rv = PR_SetNetAddr(PR_IpAddrAny, PR_AF_INET6, DEFAULT_PORT,
&serverAddress);
rv = PR_Bind(server->listener, &serverAddress);
TEST_ASSERT(PR_SUCCESS == rv);
rv = PR_Listen(server->listener, server->backlog);
TEST_ASSERT(PR_SUCCESS == rv);
server->started = PR_IntervalNow();
TimeOfDayMessage("Server started at", me);
PR_Lock(server->ml);
server->state = cs_run;
PR_NotifyCondVar(server->stateChange);
PR_Unlock(server->ml);
/*
** Create the first worker (actually, a thread that accepts
** connections and then processes the work load as needed).
** From this point on, additional worker threads are created
** as they are needed by existing worker threads.
*/
rv = CreateWorker(server, &server->pool);
TEST_ASSERT(PR_SUCCESS == rv);
/*
** From here on this thread is merely hanging around as the contact
** point for the main test driver. It's just waiting for the driver
** to declare the test complete.
*/
TEST_LOG(
cltsrv_log_file, TEST_LOG_VERBOSE,
("\tServer(0x%p): waiting for state change\n", me));
PR_Lock(server->ml);
while ((cs_run == server->state) && !Aborted(rv))
{
rv = PR_WaitCondVar(server->stateChange, PR_INTERVAL_NO_TIMEOUT);
}
PR_Unlock(server->ml);
PR_ClearInterrupt();
TEST_LOG(
cltsrv_log_file, TEST_LOG_INFO,
("\tServer(0x%p): shutting down workers\n", me));
/*
** Get all the worker threads to exit. They know how to
** clean up after themselves, so this is just a matter of
** waiting for clorine in the pool to take effect. During
** this stage we're ignoring interrupts.
*/
server->workers.minimum = server->workers.maximum = 0;
PR_Lock(server->ml);
while (!PR_CLIST_IS_EMPTY(&server->list))
{
PRCList *head = PR_LIST_HEAD(&server->list);
CSWorker_t *worker = (CSWorker_t*)head;
TEST_LOG(
cltsrv_log_file, TEST_LOG_VERBOSE,
("\tServer(0x%p): interrupting worker(0x%p)\n", me, worker));
rv = PR_Interrupt(worker->thread);
TEST_ASSERT(PR_SUCCESS == rv);
PR_REMOVE_AND_INIT_LINK(head);
}
while (server->pool.workers > 0)
{
TEST_LOG(
cltsrv_log_file, TEST_LOG_NOTICE,
("\tServer(0x%p): waiting for %u workers to exit\n",
me, server->pool.workers));
(void)PR_WaitCondVar(server->pool.exiting, PR_INTERVAL_NO_TIMEOUT);
}
server->state = cs_exit;
PR_NotifyCondVar(server->stateChange);
PR_Unlock(server->ml);
TEST_LOG(
//.........这里部分代码省略.........
请发表评论