SimpleAI
 All Classes Namespaces Files Functions Variables Typedefs Macros Groups Pages
Zone.h
Go to the documentation of this file.
1 
14 #pragma once
15 
16 #include "ICharacter.h"
17 #include "group/GroupMgr.h"
18 #include "common/Thread.h"
19 #include "common/ThreadPool.h"
20 #include "common/Types.h"
21 #include "common/ExecutionTime.h"
22 #include <unordered_map>
23 #include <vector>
24 #include <memory>
25 
26 namespace ai {
27 
28 class AI;
29 typedef std::shared_ptr<AI> AIPtr;
30 
40 class Zone {
41 public:
42  typedef std::unordered_map<CharacterId, AIPtr> AIMap;
43  typedef std::vector<AIPtr> AIScheduleList;
44  typedef std::vector<CharacterId> CharacterIdList;
45  typedef AIMap::const_iterator AIMapConstIter;
46  typedef AIMap::iterator AIMapIter;
47 
48 protected:
49  const std::string _name;
50  AIMap _ais;
51  AIScheduleList _scheduledAdd;
52  AIScheduleList _scheduledRemove;
53  CharacterIdList _scheduledDestroy;
54  bool _debug;
55  ReadWriteLock _lock {"zone"};
56  ReadWriteLock _scheduleLock {"zone-schedulelock"};
57  ai::GroupMgr _groupManager;
58  mutable ThreadPool _threadPool;
59 
66  bool doAddAI(const AIPtr& ai);
70  bool doRemoveAI(const AIPtr& ai);
78  bool doDestroyAI(const CharacterId& id);
79 
80 public:
81  Zone(const std::string& name, int threadCount = std::min(1u, std::thread::hardware_concurrency())) :
82  _name(name), _debug(false), _threadPool(threadCount) {
83  }
84 
85  virtual ~Zone() {}
86 
92  void update(int64_t dt);
93 
100  bool addAI(const AIPtr& ai);
101 
106  template<class Collection>
107  bool addAIs(const Collection& ais) {
108  if (ais.empty()) {
109  return false;
110  }
111  ScopedWriteLock scopedLock(_scheduleLock);
112  _scheduledAdd.insert(_scheduledAdd.end(), ais.begin(), ais.end());
113  return true;
114  }
115 
121  bool removeAI(const AIPtr& ai);
122 
127  template<class Collection>
128  bool removeAIs(const Collection& ais) {
129  if (ais.empty()) {
130  return false;
131  }
132  ScopedWriteLock scopedLock(_scheduleLock);
133  _scheduledRemove.insert(_scheduledRemove.end(), ais.begin(), ais.end());
134  return true;
135  }
136 
144  bool destroyAI(const CharacterId& id);
145 
149  const std::string& getName() const;
150 
157  void setDebug(bool debug);
158  bool isDebug () const;
159 
160  GroupMgr& getGroupMgr();
161 
162  const GroupMgr& getGroupMgr() const;
163 
171  inline AIPtr getAI(CharacterId id) const {
172  ScopedReadLock scopedLock(_lock);
173  auto i = _ais.find(id);
174  if (i == _ais.end()) {
175  return AIPtr();
176  }
177  const AIPtr& ai = i->second;
178  return ai;
179  }
180 
192  template<typename Func>
193  inline bool executeAsync(CharacterId id, const Func& func) const {
194  const AIPtr& ai = getAI(id);
195  if (!ai) {
196  return false;
197  }
198  executeAsync(ai, func);
199  return true;
200  }
201 
210  template<typename Func>
211  inline auto executeAsync(const AIPtr& ai, const Func& func) const
212  -> std::future<typename std::result_of<Func(const AIPtr&)>::type> {
213  return _threadPool.enqueue(func, ai);
214  }
215 
216  template<typename Func>
217  inline auto execute(const AIPtr& ai, const Func& func) const
218  -> typename std::result_of<Func(const AIPtr&)>::type {
219  return func(ai);
220  }
221 
222  template<typename Func>
223  inline auto execute(const AIPtr& ai, Func& func)
224  -> typename std::result_of<Func(const AIPtr&)>::type {
225  return func(ai);
226  }
227 
233  template<typename Func>
234  inline auto execute(CharacterId id, const Func& func) const
235  -> typename std::result_of<Func(const AIPtr&)>::type {
236  return execute(getAI(id), func);
237  }
238 
244  template<typename Func>
245  inline auto execute(CharacterId id, Func& func)
246  -> typename std::result_of<Func(const AIPtr&)>::type {
247  return execute(getAI(id), func);
248  }
249 
257  template<typename Func>
258  void executeParallel(Func& func) {
259  std::vector<std::future<void> > results;
260  _lock.lockRead();
261  AIMap copy(_ais);
262  _lock.unlockRead();
263  for (auto i = copy.begin(); i != copy.end(); ++i) {
264  const AIPtr& ai = i->second;
265  results.emplace_back(executeAsync(ai, func));
266  }
267  for (auto & result: results) {
268  result.wait();
269  }
270  }
271 
279  template<typename Func>
280  void executeParallel(const Func& func) const {
281  std::vector<std::future<void> > results;
282  _lock.lockRead();
283  AIMap copy(_ais);
284  _lock.unlockRead();
285  for (auto i = copy.begin(); i != copy.end(); ++i) {
286  const AIPtr& ai = i->second;
287  results.emplace_back(executeAsync(ai, func));
288  }
289  for (auto & result: results) {
290  result.wait();
291  }
292  }
293 
300  template<typename Func>
301  void execute(const Func& func) const {
302  _lock.lockRead();
303  AIMap copy(_ais);
304  _lock.unlockRead();
305  for (auto i = copy.begin(); i != copy.end(); ++i) {
306  const AIPtr& ai = i->second;
307  func(ai);
308  }
309  }
310 
317  template<typename Func>
318  void execute(Func& func) {
319  _lock.lockRead();
320  AIMap copy(_ais);
321  _lock.unlockRead();
322  for (auto i = copy.begin(); i != copy.end(); ++i) {
323  const AIPtr& ai = i->second;
324  func(ai);
325  }
326  }
327 
328  inline std::size_t size() const {
329  ScopedReadLock scopedLock(_lock);
330  return _ais.size();
331  }
332 };
333 
334 inline void Zone::setDebug (bool debug) {
335  _debug = debug;
336 }
337 
338 inline bool Zone::isDebug () const {
339  return _debug;
340 }
341 
342 inline const std::string& Zone::getName() const {
343  return _name;
344 }
345 
346 inline GroupMgr& Zone::getGroupMgr() {
347  return _groupManager;
348 }
349 
350 inline const GroupMgr& Zone::getGroupMgr() const {
351  return _groupManager;
352 }
353 
354 inline bool Zone::doAddAI(const AIPtr& ai) {
355  if (ai == nullptr) {
356  return false;
357  }
358  const CharacterId& id = ai->getCharacter()->getId();
359  if (_ais.find(id) != _ais.end()) {
360  return false;
361  }
362  _ais.insert(std::make_pair(id, ai));
363  ai->setZone(this);
364  return true;
365 }
366 
367 inline bool Zone::doRemoveAI(const AIPtr& ai) {
368  if (!ai) {
369  return false;
370  }
371  const CharacterId& id = ai->getCharacter()->getId();
372  AIMapIter i = _ais.find(id);
373  if (i == _ais.end()) {
374  return false;
375  }
376  i->second->setZone(nullptr);
377  _groupManager.removeFromAllGroups(i->second);
378  _ais.erase(i);
379  return true;
380 }
381 
382 inline bool Zone::doDestroyAI(const CharacterId& id) {
383  AIMapIter i = _ais.find(id);
384  if (i == _ais.end()) {
385  return false;
386  }
387  _ais.erase(i);
388  return true;
389 }
390 
391 inline bool Zone::addAI(const AIPtr& ai) {
392  if (!ai) {
393  return false;
394  }
395  ScopedWriteLock scopedLock(_scheduleLock);
396  _scheduledAdd.push_back(ai);
397  return true;
398 }
399 
400 inline bool Zone::destroyAI(const CharacterId& id) {
401  ScopedWriteLock scopedLock(_scheduleLock);
402  _scheduledDestroy.push_back(id);
403  return true;
404 }
405 
406 inline bool Zone::removeAI(const AIPtr& ai) {
407  if (!ai) {
408  return false;
409  }
410  ScopedWriteLock scopedLock(_scheduleLock);
411  _scheduledRemove.push_back(ai);
412  return true;
413 }
414 
415 inline void Zone::update(int64_t dt) {
416  {
417  AIScheduleList scheduledRemove;
418  AIScheduleList scheduledAdd;
419  CharacterIdList scheduledDestroy;
420  {
421  ScopedWriteLock scopedLock(_scheduleLock);
422  scheduledAdd.swap(_scheduledAdd);
423  scheduledRemove.swap(_scheduledRemove);
424  scheduledDestroy.swap(_scheduledDestroy);
425  }
426  ScopedWriteLock scopedLock(_lock);
427  for (const AIPtr& ai : scheduledAdd) {
428  doAddAI(ai);
429  }
430  scheduledAdd.clear();
431  for (const AIPtr& ai : scheduledRemove) {
432  doRemoveAI(ai);
433  }
434  scheduledRemove.clear();
435  for (auto id : scheduledDestroy) {
436  doDestroyAI(id);
437  }
438  scheduledDestroy.clear();
439  }
440 
441  auto func = [&] (const AIPtr& ai) {
442  if (ai->isPause()) {
443  return;
444  }
445  ai->update(dt, _debug);
446  ai->getBehaviour()->execute(ai, dt);
447  };
448  executeParallel(func);
449  _groupManager.update(dt);
450 }
451 
452 }
Maintains the groups a AI can be in.
Definition: GroupMgr.h:27