1/**
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef MOCK_RIL_WORKER_H_
18#define MOCK_RIL_WORKER_H_
19
20#include <queue>
21#include <list>
22#include <vector>
23#include <pthread.h>
24#include <cutils/atomic.h>
25#include <utils/SystemClock.h>
26
27/**
28 * A Thread class.
29 *
30 * 0) Extend WorkerThread creating a Worker method which
31 *    monitors isRunning(). For example:
32 *
33 *   void * Worker(void *param) {
34 *       while (isRunning() == 0) {
35 *           pthread_mutex_lock(&mutex_);
36 *           while (isRunning() && !SOME-CONDITION) {
37 *               pthread_cond_wait(&cond_, &mutex_);
38 *           }
39 *           if (isRunning()) {
40 *               DO-WORK
41 *           } else {
42 *               pthread_mutex_unlock(&mutex_);
43 *           }
44 *       }
45 *       return NULL;
46 *   }
47 *
48 * 1) Create the WorkerThread.
49 * 2) Execute Run passing a param which will be passed to Worker.
50 * 3) Call Stop() or destroy the thread to stop processing.
51 *
52 */
53class WorkerThread {
54  protected:
55    pthread_attr_t attr_;
56    pthread_mutex_t mutex_;
57    pthread_cond_t cond_;
58    pthread_t tid_;
59    void *workerParam_;
60
61    #define STATE_INITIALIZED   1
62    #define STATE_RUNNING       2
63    #define STATE_STOPPING      3
64    #define STATE_STOPPED       4
65    int32_t state_;
66
67    static void * Work(void *param);
68
69    virtual bool isRunning();
70
71  public:
72    WorkerThread();
73
74    virtual ~WorkerThread();
75
76    // Return true if changed from STATE_RUNNING to STATE_STOPPING
77    virtual bool BeginStopping();
78
79    // Wait until state is not STATE_STOPPING
80    virtual void WaitUntilStopped();
81
82    virtual void Stop();
83
84    virtual int Run(void *workerParam);
85
86    /**
87     * Method called to do work, see example above.
88     * While running isRunning() must be monitored.
89     */
90    virtual void *Worker(void *) = 0;
91};
92
93
94/**
95 * A WorkerQueue.
96 *
97 * 0) Extend overriding Process
98 * 1) Create an instance
99 * 2) Call Run.
100 * 3) Call Add, passing a pointer which is added to a queue
101 * 4) Process will be called with a pointer as work can be done.
102 */
103class WorkerQueue {
104  private:
105    friend class WorkerQueueThread;
106
107    struct Record {
108        int64_t time;
109        void *p;
110    };
111
112    class record_compare {
113      public:
114        // To get ascending order return true if lhs > rhs.
115        bool operator() (const struct Record* lhs, const struct Record* rhs) const {
116            return lhs->time > rhs->time;
117        }
118    };
119
120    std::list<struct Record *> q_;                // list of records to be processed
121    std::list<struct Record *> free_list_;        // list of records that have been released
122    std::priority_queue<struct Record *, std::vector<struct Record *>, record_compare> delayed_q_;
123                                                  // list of records that are delayed
124    class WorkerQueueThread *wqt_;
125
126  protected:
127    struct Record *obtain_record(void *p, int delay_in_ms);
128
129    void release_record(struct Record *r);
130
131  public:
132    WorkerQueue();
133
134    virtual ~WorkerQueue();
135
136    int Run();
137
138    void Stop();
139
140    void Add(void *p);
141
142    void AddDelayed(void *p, int delay_in_ms);
143
144    virtual void Process(void *) = 0;
145};
146
147extern void testWorker();
148
149#endif // MOCK_RIL_WORKER_H_
150