1/*
2 * Copyright 2007, The Android Open Source Project
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *  * Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 *  * Redistributions in binary form must reproduce the above copyright
10 *    notice, this list of conditions and the following disclaimer in the
11 *    documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include "config.h"
27#include "JavaSharedClient.h"
28#include "TimerClient.h"
29#include "SkDeque.h"
30#include "SkThread.h"
31
32namespace android {
33    TimerClient* JavaSharedClient::GetTimerClient()
34    {
35        return gTimerClient;
36    }
37
38    CookieClient* JavaSharedClient::GetCookieClient()
39    {
40        return gCookieClient;
41    }
42
43    PluginClient* JavaSharedClient::GetPluginClient()
44    {
45        return gPluginClient;
46    }
47
48    KeyGeneratorClient* JavaSharedClient::GetKeyGeneratorClient()
49    {
50        return gKeyGeneratorClient;
51    }
52
53    void JavaSharedClient::SetTimerClient(TimerClient* client)
54    {
55        gTimerClient = client;
56    }
57
58    void JavaSharedClient::SetCookieClient(CookieClient* client)
59    {
60        gCookieClient = client;
61    }
62
63    void JavaSharedClient::SetPluginClient(PluginClient* client)
64    {
65        gPluginClient = client;
66    }
67
68    void JavaSharedClient::SetKeyGeneratorClient(KeyGeneratorClient* client)
69    {
70        gKeyGeneratorClient = client;
71    }
72
73    TimerClient*    JavaSharedClient::gTimerClient = NULL;
74    CookieClient*   JavaSharedClient::gCookieClient = NULL;
75    PluginClient*   JavaSharedClient::gPluginClient = NULL;
76    KeyGeneratorClient* JavaSharedClient::gKeyGeneratorClient = NULL;
77
78    ///////////////////////////////////////////////////////////////////////////
79
80    struct FuncPtrRec {
81        void (*fProc)(void* payload);
82        void* fPayload;
83    };
84
85    static SkMutex gFuncPtrQMutex;
86    static SkDeque gFuncPtrQ(sizeof(FuncPtrRec));
87
88    void JavaSharedClient::EnqueueFunctionPtr(void (*proc)(void* payload),
89                                              void* payload)
90    {
91        gFuncPtrQMutex.acquire();
92
93        FuncPtrRec* rec = (FuncPtrRec*)gFuncPtrQ.push_back();
94        rec->fProc = proc;
95        rec->fPayload = payload;
96
97        gFuncPtrQMutex.release();
98
99        gTimerClient->signalServiceFuncPtrQueue();
100    }
101
102    void JavaSharedClient::ServiceFunctionPtrQueue()
103    {
104        for (;;) {
105            void (*proc)(void*) = 0;
106            void* payload = 0;
107            const FuncPtrRec* rec;
108
109            // we have to copy the proc/payload (if present). we do this so we
110            // don't call the proc inside the mutex (possible deadlock!)
111            gFuncPtrQMutex.acquire();
112            rec = (const FuncPtrRec*)gFuncPtrQ.front();
113            if (rec) {
114                proc = rec->fProc;
115                payload = rec->fPayload;
116                gFuncPtrQ.pop_front();
117            }
118            gFuncPtrQMutex.release();
119
120            if (!rec)
121                break;
122            proc(payload);
123        }
124    }
125}
126