FireBreath  1.4.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Pages
OneShotManager.mm
1 
2 /**********************************************************\
3  Original Author: Georg Fritzsche
4 
5  Created: Nov 6, 2010
6  License: Dual license model; choose one of two:
7  New BSD License
8  http://www.opensource.org/licenses/bsd-license.php
9  - or -
10  GNU Lesser General Public License, version 2.1
11  http://www.gnu.org/licenses/lgpl-2.1.html
12 
13  Copyright 2010 Georg Fritzsche and the Firebreath development team
14  \**********************************************************/
15 
16 #include "OneShotManager.h"
17 #import <Cocoa/Cocoa.h>
18 #include <iostream>
19 #include <fstream>
20 #include <cassert>
21 
22 @interface OneShotManagerHelper : NSObject {
23  FB::OneShotManager* m_manager;
24 }
25 
26 - (void)shoot:(id)object;
27 
28 @end
29 
30 @implementation OneShotManagerHelper
31 
32 - (void)setManager:(FB::OneShotManager*) manager
33 {
34  m_manager = manager;
35 }
36 - (FB::OneShotManager*)manager
37 {
38  return m_manager;
39 }
40 
41 - (void)shoot:(id)object {
42  if (m_manager)
43  m_manager->npp_asyncCallback();
44 }
45 
46 @end
47 
48 FB::OneShotManager::OneShotManager() : m_helper(NULL), m_shots(0)
49 {
50  OneShotManagerHelper* mHelper = [OneShotManagerHelper new];
51  [mHelper setManager:this];
52  m_helper = mHelper;
53 }
54 
55 FB::OneShotManager::~OneShotManager()
56 {
57  OneShotManagerHelper* mHelper = (OneShotManagerHelper*) m_helper;
58  [mHelper release];
59  mHelper = NULL;
60 }
61 
62 void FB::OneShotManager::npp_register(void* instance) {
63  // If there isn't a deque for the instance, create it.
64  boost::mutex::scoped_lock lock(m_mutex);
65  std::map<void*,SinkQueue*>::iterator sink = m_sinks.find(instance);
66  if (m_sinks.end() == sink)
67  m_sinks[instance] = new SinkQueue();
68 }
69 void FB::OneShotManager::npp_unregister(void* instance) {
70  // If there is a deque for the instance, destroy it and all callbacks.
71  boost::mutex::scoped_lock lock(m_mutex);
72  std::map<void*,SinkQueue*>::iterator sink = m_sinks.find(instance);
73  if (m_sinks.end() != sink) {
74  m_shots -= sink->second->size();
75  delete sink->second;
76  m_sinks.erase(sink);
77  }
78 }
79 
80 void FB::OneShotManager::npp_scheduleAsyncCallback(void* instance, OneShotCallback func, void *userData) {
81  // If there is a deque for the instance, add the callback.
82  boost::mutex::scoped_lock lock(m_mutex);
83  std::map<void*,SinkQueue*>::iterator sink = m_sinks.find(instance);
84  if (m_sinks.end() != sink) {
85  sink->second->push_back(std::make_pair(userData, func));
86  if (!m_shots) {
87  OneShotManagerHelper* mHelper = (OneShotManagerHelper*) m_helper;
88  [mHelper performSelectorOnMainThread:@selector(shoot:) withObject:NULL waitUntilDone:NO];
89  }
90  m_shots++;
91  }
92 }
93 
94 bool FB::OneShotManager::npp_nextCallback(SinkPair& callback) {
95  // return the next callback.
96  boost::mutex::scoped_lock lock(m_mutex);
97  std::map<void*,SinkQueue*>::iterator sink = m_sinks.begin();
98  while (m_sinks.end() != sink) {
99  SinkQueue::iterator call = sink->second->begin();
100  if (sink->second->end() != call) {
101  callback = *call;
102  sink->second->erase(call);
103  m_shots--;
104  return true;
105  }
106  sink++;
107  }
108  return false;
109 }
110 
111 void FB::OneShotManager::npp_asyncCallback() {
112  // Must be on main thread.
113  // This is done this way because Safari may call NPP_Destroy during the callback.
114  SinkPair callback;
115  while (npp_nextCallback(callback))
116  callback.second(callback.first);
117 }
118 
119 FB::OneShotManager& FB::OneShotManager::getInstance()
120 {
121  static OneShotManager manager;
122  return manager;
123 }