1363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger/*
2363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger * Copyright 2012 Google Inc.
3363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger *
4363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger * Use of this source code is governed by a BSD-style license that can be
5363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger * found in the LICENSE file.
6363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger */
7363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
8363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger#ifndef SkThreadPool_DEFINED
9363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger#define SkThreadPool_DEFINED
10363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
11363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger#include "SkCondVar.h"
120a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger#include "SkRunnable.h"
13363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger#include "SkTDArray.h"
14363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger#include "SkTInternalLList.h"
15363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
16363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergerclass SkThread;
17363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
18363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergerclass SkThreadPool {
19363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
20363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergerpublic:
21363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    /**
227839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger     * Create a threadpool with count threads, or one thread per core if kThreadPerCore.
23363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger     */
247839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    static const int kThreadPerCore = -1;
25363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    explicit SkThreadPool(int count);
26363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    ~SkThreadPool();
27363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
28363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    /**
29363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger     * Queues up an SkRunnable to run when a thread is available, or immediately if
30363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger     * count is 0.  NULL is a safe no-op.  Does not take ownership.
31363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger     */
32363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    void add(SkRunnable*);
33363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
340a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    /**
350a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger     * Block until all added SkRunnables have completed.  Once called, calling add() is undefined.
360a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger     */
370a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    void wait();
380a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger
39363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger private:
40363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    struct LinkedRunnable {
41363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        // Unowned pointer.
42363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        SkRunnable* fRunnable;
43363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
44363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    private:
45363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        SK_DECLARE_INTERNAL_LLIST_INTERFACE(LinkedRunnable);
46363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    };
47363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
480a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    enum State {
490a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        kRunning_State,  // Normal case.  We've been constructed and no one has called wait().
500a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        kWaiting_State,  // wait has been called, but there still might be work to do or being done.
510a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        kHalting_State,  // There's no work to do and no thread is busy.  All threads can shut down.
520a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    };
530a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger
540a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    SkTInternalLList<LinkedRunnable> fQueue;
550a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    SkCondVar                        fReady;
560a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    SkTDArray<SkThread*>             fThreads;
570a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    State                            fState;
580a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    int                              fBusyThreads;
59363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
60363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    static void Loop(void*);  // Static because we pass in this.
61363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger};
62363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
63363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger#endif
64