js/src/vm/ThreadPool.h
author Ehsan Akhgari <ehsan@mozilla.com>
Sun, 20 Oct 2013 09:10:07 -0400
changeset 166237 0ddbf9b3b20c8f4a799cf36a1778f55ee759b17b
parent 159040 9e98958b5e50ca9456adb49750e6480ac7ad201d
child 166239 0bf3c7b93cabf9287f0b27ec7850f4ab28f1e145
permissions -rw-r--r--
Bug 928712 = Remove the rest of the unneeded prtypes.h inclusions; rs=bsmedberg

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
 * vim: set ts=8 sts=4 et sw=4 tw=99:
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef vm_ThreadPool_h
#define vm_ThreadPool_h

#include <stddef.h>
#include <stdint.h>

#include "jsalloc.h"
#include "jspubtd.h"
#ifdef JS_THREADSAFE
# include "prcvar.h"
# include "prlock.h"
#endif

#include "js/Vector.h"

struct JSRuntime;
struct JSCompartment;

namespace js {

class ThreadPoolWorker;

typedef void (*TaskFun)(void *userdata, uint32_t workerId, uintptr_t stackLimit);

class TaskExecutor
{
  public:
    virtual void executeFromWorker(uint32_t workerId, uintptr_t stackLimit) = 0;
};

// ThreadPool used for parallel JavaScript execution as well as
// parallel compilation.  Unless you are building a new kind of
// parallel service, it is very likely that you do not wish to
// interact with the threadpool directly.  In particular, if you wish
// to execute JavaScript in parallel, you probably want to look at
// |js::ForkJoin| in |forkjoin.cpp|.
//
// The ThreadPool always maintains a fixed pool of worker threads.
// You can query the number of worker threads via the method
// |numWorkers()|.  Note that this number may be zero (generally if
// threads are disabled, or when manually specified for benchmarking
// purposes).
//
// The way to submit a job is using |submitAll()|---in this
// case, the job will be executed by all worker threads.  This does
// not fail if there are no worker threads, it simply does nothing.
// Of course, each thread may have any number of previously submitted
// things that they are already working on, and so they will finish
// those before they get to this job.  Therefore it is possible to
// have some worker threads pick up (and even finish) their piece of
// the job before others have even started.
class ThreadPool
{
  private:
    friend class ThreadPoolWorker;

    // Initialized at startup only:
#if defined(JS_THREADSAFE) || defined(DEBUG)
    JSRuntime *const runtime_;
#endif
    js::Vector<ThreadPoolWorker*, 8, SystemAllocPolicy> workers_;

    // Number of workers we will start, when we actually start them
    size_t numWorkers_;

    bool lazyStartWorkers(JSContext *cx);
    void terminateWorkers();
    void terminateWorkersAndReportOOM(JSContext *cx);

  public:
    ThreadPool(JSRuntime *rt);
    ~ThreadPool();

    bool init();

    // Return number of worker threads in the pool.
    size_t numWorkers() { return numWorkers_; }

    // See comment on class:
    bool submitAll(JSContext *cx, TaskExecutor *executor);

    // Wait until all worker threads have finished their current set
    // of jobs and then return.  You must not submit new jobs after
    // invoking |terminate()|.
    bool terminate();
};

} // namespace js

#endif /* vm_ThreadPool_h */