2
0

asyncTaskManager.cxx 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748
  1. // Filename: asyncTaskManager.cxx
  2. // Created by: drose (23Aug06)
  3. //
  4. ////////////////////////////////////////////////////////////////////
  5. //
  6. // PANDA 3D SOFTWARE
  7. // Copyright (c) Carnegie Mellon University. All rights reserved.
  8. //
  9. // All use of this software is subject to the terms of the revised BSD
  10. // license. You should have received a copy of this license along
  11. // with this source code in a file named "LICENSE."
  12. //
  13. ////////////////////////////////////////////////////////////////////
  14. #include "asyncTaskManager.h"
  15. #include "event.h"
  16. #include "pt_Event.h"
  17. #include "mutexHolder.h"
  18. #include "indent.h"
  19. #include "pStatClient.h"
  20. #include "pStatTimer.h"
  21. #include "clockObject.h"
  22. #include "config_event.h"
  23. #include <algorithm>
  24. AsyncTaskManager *AsyncTaskManager::_global_ptr = NULL;
  25. TypeHandle AsyncTaskManager::_type_handle;
  26. ////////////////////////////////////////////////////////////////////
  27. // Function: AsyncTaskManager::Constructor
  28. // Access: Published
  29. // Description:
  30. ////////////////////////////////////////////////////////////////////
  31. AsyncTaskManager::
  32. AsyncTaskManager(const string &name) :
  33. Namable(name),
  34. _lock("AsyncTaskManager::_lock"),
  35. _num_tasks(0),
  36. _clock(ClockObject::get_global_clock()),
  37. _frame_cvar(_lock)
  38. {
  39. // Make a default task chain.
  40. do_make_task_chain("default");
  41. }
  42. ////////////////////////////////////////////////////////////////////
  43. // Function: AsyncTaskManager::Destructor
  44. // Access: Published, Virtual
  45. // Description:
  46. ////////////////////////////////////////////////////////////////////
  47. AsyncTaskManager::
  48. ~AsyncTaskManager() {
  49. cleanup();
  50. }
  51. ////////////////////////////////////////////////////////////////////
  52. // Function: AsyncTaskManager::cleanup
  53. // Access: Published
  54. // Description: Stops all threads and messily empties the task list.
  55. // This is intended to be called on destruction only.
  56. ////////////////////////////////////////////////////////////////////
  57. void AsyncTaskManager::
  58. cleanup() {
  59. MutexHolder holder(_lock);
  60. if (task_cat.is_debug()) {
  61. do_output(task_cat.debug());
  62. task_cat.debug(false)
  63. << ": cleanup()\n";
  64. }
  65. // Iterate carefully in case the tasks adjust the chain list within
  66. // cleanup().
  67. while (!_task_chains.empty()) {
  68. PT(AsyncTaskChain) chain = _task_chains[_task_chains.size() - 1];
  69. _task_chains.pop_back();
  70. chain->do_cleanup();
  71. }
  72. // There might be one remaining task, the current task. Especially
  73. // if it wasn't running on a thread.
  74. if (_num_tasks == 1) {
  75. nassertv(_tasks_by_name.size() == 1);
  76. TasksByName::const_iterator tbni = _tasks_by_name.begin();
  77. AsyncTask *task = (*tbni);
  78. nassertv(task->_state == AsyncTask::S_servicing ||
  79. task->_state == AsyncTask::S_servicing_removed);
  80. task->_state = AsyncTask::S_servicing_removed;
  81. } else {
  82. // If there isn't exactly one remaining task, there should be
  83. // none.
  84. #ifndef NDEBUG
  85. nassertd(_num_tasks == 0 && _tasks_by_name.empty()) {
  86. task_cat.error()
  87. << "_num_tasks = " << _num_tasks << " _tasks_by_name = " << _tasks_by_name.size() << "\n";
  88. TasksByName::const_iterator tbni;
  89. for (tbni = _tasks_by_name.begin();
  90. tbni != _tasks_by_name.end();
  91. ++tbni) {
  92. task_cat.error()
  93. << " " << *(*tbni) << "\n";
  94. }
  95. }
  96. #endif // NDEBUG
  97. }
  98. }
  99. ////////////////////////////////////////////////////////////////////
  100. // Function: AsyncTaskManager::get_num_task_chains
  101. // Access: Published
  102. // Description: Returns the number of different task chains.
  103. ////////////////////////////////////////////////////////////////////
  104. int AsyncTaskManager::
  105. get_num_task_chains() const {
  106. MutexHolder holder(_lock);
  107. return _task_chains.size();
  108. }
  109. ////////////////////////////////////////////////////////////////////
  110. // Function: AsyncTaskManager::get_task_chain
  111. // Access: Published
  112. // Description: Returns the nth task chain.
  113. ////////////////////////////////////////////////////////////////////
  114. AsyncTaskChain *AsyncTaskManager::
  115. get_task_chain(int n) const {
  116. MutexHolder holder(_lock);
  117. nassertr(n >= 0 && n < (int)_task_chains.size(), NULL);
  118. return _task_chains[n];
  119. }
  120. ////////////////////////////////////////////////////////////////////
  121. // Function: AsyncTaskManager::make_task_chain
  122. // Access: Published
  123. // Description: Creates a new AsyncTaskChain of the indicated name
  124. // and stores it within the AsyncTaskManager. If a task
  125. // chain with this name already exists, returns it
  126. // instead.
  127. ////////////////////////////////////////////////////////////////////
  128. AsyncTaskChain *AsyncTaskManager::
  129. make_task_chain(const string &name) {
  130. MutexHolder holder(_lock);
  131. return do_make_task_chain(name);
  132. }
  133. ////////////////////////////////////////////////////////////////////
  134. // Function: AsyncTaskManager::find_task_chain
  135. // Access: Protected
  136. // Description: Searches a new AsyncTaskChain of the indicated name
  137. // and returns it if it exists, or NULL otherwise.
  138. ////////////////////////////////////////////////////////////////////
  139. AsyncTaskChain *AsyncTaskManager::
  140. find_task_chain(const string &name) {
  141. MutexHolder holder(_lock);
  142. return do_find_task_chain(name);
  143. }
  144. ////////////////////////////////////////////////////////////////////
  145. // Function: AsyncTaskManager::remove_task_chain
  146. // Access: Protected
  147. // Description: Removes the AsyncTaskChain of the indicated name.
  148. // If the chain still has tasks, this will block until
  149. // all tasks are finished.
  150. //
  151. // Returns true if successful, or false if the chain did
  152. // not exist.
  153. ////////////////////////////////////////////////////////////////////
  154. bool AsyncTaskManager::
  155. remove_task_chain(const string &name) {
  156. MutexHolder holder(_lock);
  157. PT(AsyncTaskChain) chain = new AsyncTaskChain(this, name);
  158. TaskChains::iterator tci = _task_chains.find(chain);
  159. if (tci == _task_chains.end()) {
  160. // No chain.
  161. return false;
  162. }
  163. chain = (*tci);
  164. while (chain->_num_tasks != 0) {
  165. // Still has tasks.
  166. task_cat.info()
  167. << "Waiting for tasks on chain " << name << " to finish.\n";
  168. chain->do_wait_for_tasks();
  169. }
  170. // Safe to remove.
  171. chain->do_cleanup();
  172. _task_chains.erase(tci);
  173. return true;
  174. }
  175. ////////////////////////////////////////////////////////////////////
  176. // Function: AsyncTaskManager::add
  177. // Access: Published
  178. // Description: Adds the indicated task to the active queue. It is
  179. // an error if the task is already added to this or any
  180. // other active queue.
  181. ////////////////////////////////////////////////////////////////////
  182. void AsyncTaskManager::
  183. add(AsyncTask *task) {
  184. nassertv(task->is_runnable());
  185. {
  186. MutexHolder holder(_lock);
  187. if (task_cat.is_debug()) {
  188. task_cat.debug()
  189. << "Adding " << *task << "\n";
  190. }
  191. if (task->_state == AsyncTask::S_servicing_removed) {
  192. if (task->_manager == this) {
  193. // Re-adding a self-removed task; this just means clearing the
  194. // removed flag.
  195. task->_state = AsyncTask::S_servicing;
  196. return;
  197. }
  198. }
  199. nassertv(task->_manager == NULL &&
  200. task->_state == AsyncTask::S_inactive);
  201. nassertv(!do_has_task(task));
  202. _lock.release();
  203. task->upon_birth(this);
  204. _lock.acquire();
  205. nassertv(task->_manager == NULL &&
  206. task->_state == AsyncTask::S_inactive);
  207. nassertv(!do_has_task(task));
  208. AsyncTaskChain *chain = do_find_task_chain(task->_chain_name);
  209. if (chain == (AsyncTaskChain *)NULL) {
  210. task_cat.warning()
  211. << "Creating implicit AsyncTaskChain " << task->_chain_name
  212. << " for " << get_type() << " " << get_name() << "\n";
  213. chain = do_make_task_chain(task->_chain_name);
  214. }
  215. chain->do_add(task);
  216. }
  217. }
  218. ////////////////////////////////////////////////////////////////////
  219. // Function: AsyncTaskManager::has_task
  220. // Access: Published
  221. // Description: Returns true if the indicated task has been added to
  222. // this AsyncTaskManager, false otherwise.
  223. ////////////////////////////////////////////////////////////////////
  224. bool AsyncTaskManager::
  225. has_task(AsyncTask *task) const {
  226. MutexHolder holder(_lock);
  227. if (task->_manager != this) {
  228. nassertr(!do_has_task(task), false);
  229. return false;
  230. }
  231. if (task->_state == AsyncTask::S_servicing_removed) {
  232. return false;
  233. }
  234. // The task might not actually be in the active queue, since it
  235. // might be being serviced right now. That's OK.
  236. return true;
  237. }
  238. ////////////////////////////////////////////////////////////////////
  239. // Function: AsyncTaskManager::find_task
  240. // Access: Published
  241. // Description: Returns the first task found with the indicated name,
  242. // or NULL if there is no task with the indicated name.
  243. //
  244. // If there are multiple tasks with the same name,
  245. // returns one of them arbitrarily.
  246. ////////////////////////////////////////////////////////////////////
  247. AsyncTask *AsyncTaskManager::
  248. find_task(const string &name) const {
  249. AsyncTask sample_task(name);
  250. sample_task.local_object();
  251. TasksByName::const_iterator tbni = _tasks_by_name.lower_bound(&sample_task);
  252. if (tbni != _tasks_by_name.end() && (*tbni)->get_name() == name) {
  253. return (*tbni);
  254. }
  255. return NULL;
  256. }
  257. ////////////////////////////////////////////////////////////////////
  258. // Function: AsyncTaskManager::find_tasks
  259. // Access: Published
  260. // Description: Returns the list of tasks found with the indicated
  261. // name.
  262. ////////////////////////////////////////////////////////////////////
  263. AsyncTaskCollection AsyncTaskManager::
  264. find_tasks(const string &name) const {
  265. AsyncTask sample_task(name);
  266. sample_task.local_object();
  267. TasksByName::const_iterator tbni = _tasks_by_name.lower_bound(&sample_task);
  268. AsyncTaskCollection result;
  269. while (tbni != _tasks_by_name.end() && (*tbni)->get_name() == name) {
  270. result.add_task(*tbni);
  271. ++tbni;
  272. }
  273. return result;
  274. }
  275. ////////////////////////////////////////////////////////////////////
  276. // Function: AsyncTaskManager::find_tasks_matching
  277. // Access: Published
  278. // Description: Returns the list of tasks found whose name matches
  279. // the indicated glob pattern, e.g. "my_task_*".
  280. ////////////////////////////////////////////////////////////////////
  281. AsyncTaskCollection AsyncTaskManager::
  282. find_tasks_matching(const GlobPattern &pattern) const {
  283. string prefix = pattern.get_const_prefix();
  284. AsyncTask sample_task(prefix);
  285. sample_task.local_object();
  286. TasksByName::const_iterator tbni = _tasks_by_name.lower_bound(&sample_task);
  287. AsyncTaskCollection result;
  288. while (tbni != _tasks_by_name.end() && (*tbni)->get_name().substr(0, prefix.size()) == prefix) {
  289. AsyncTask *task = (*tbni);
  290. if (pattern.matches(task->get_name())) {
  291. result.add_task(task);
  292. }
  293. ++tbni;
  294. }
  295. return result;
  296. }
  297. ////////////////////////////////////////////////////////////////////
  298. // Function: AsyncTaskManager::remove
  299. // Access: Published
  300. // Description: Removes the indicated task from the active queue.
  301. // Returns true if the task is successfully removed, or
  302. // false if it wasn't there.
  303. ////////////////////////////////////////////////////////////////////
  304. bool AsyncTaskManager::
  305. remove(AsyncTask *task) {
  306. // We pass this up to the multi-task remove() flavor. Do we care
  307. // about the tiny cost of creating an AsyncTaskCollection here?
  308. // Probably not.
  309. AsyncTaskCollection tasks;
  310. tasks.add_task(task);
  311. return remove(tasks) != 0;
  312. }
  313. ////////////////////////////////////////////////////////////////////
  314. // Function: AsyncTaskManager::remove
  315. // Access: Published
  316. // Description: Removes all of the tasks in the AsyncTaskCollection.
  317. // Returns the number of tasks removed.
  318. ////////////////////////////////////////////////////////////////////
  319. int AsyncTaskManager::
  320. remove(const AsyncTaskCollection &tasks) {
  321. MutexHolder holder(_lock);
  322. int num_removed = 0;
  323. int num_tasks = tasks.get_num_tasks();
  324. int i;
  325. for (i = 0; i < num_tasks; ++i) {
  326. PT(AsyncTask) task = tasks.get_task(i);
  327. if (task->_manager != this) {
  328. // Not a member of this manager, or already removed.
  329. nassertr(!do_has_task(task), num_removed);
  330. } else {
  331. nassertr(task->_chain->_manager == this, num_removed);
  332. if (task_cat.is_debug()) {
  333. task_cat.debug()
  334. << "Removing " << *task << "\n";
  335. }
  336. if (task->_chain->do_remove(task)) {
  337. _lock.release();
  338. task->upon_death(this, false);
  339. _lock.acquire();
  340. ++num_removed;
  341. } else {
  342. if (task_cat.is_debug()) {
  343. task_cat.debug()
  344. << " (unable to remove " << *task << ")\n";
  345. }
  346. }
  347. }
  348. }
  349. return num_removed;
  350. }
  351. ////////////////////////////////////////////////////////////////////
  352. // Function: AsyncTaskManager::wait_for_tasks
  353. // Access: Published
  354. // Description: Blocks until the task list is empty.
  355. ////////////////////////////////////////////////////////////////////
  356. void AsyncTaskManager::
  357. wait_for_tasks() {
  358. MutexHolder holder(_lock);
  359. // Wait for each of our task chains to finish.
  360. while (_num_tasks > 0) {
  361. // We iterate through with an index, rather than with an iterator,
  362. // because it's possible for a task to adjust the task_chain list
  363. // during its execution.
  364. for (unsigned int i = 0; i < _task_chains.size(); ++i) {
  365. AsyncTaskChain *chain = _task_chains[i];
  366. chain->do_wait_for_tasks();
  367. }
  368. }
  369. }
  370. ////////////////////////////////////////////////////////////////////
  371. // Function: AsyncTaskManager::stop_threads
  372. // Access: Published
  373. // Description: Stops any threads that are currently running. If any
  374. // tasks are still pending and have not yet been picked
  375. // up by a thread, they will not be serviced unless
  376. // poll() or start_threads() is later called.
  377. ////////////////////////////////////////////////////////////////////
  378. void AsyncTaskManager::
  379. stop_threads() {
  380. MutexHolder holder(_lock);
  381. // We iterate through with an index, rather than with an iterator,
  382. // because it's possible for a task to adjust the task_chain list
  383. // during its execution.
  384. for (unsigned int i = 0; i < _task_chains.size(); ++i) {
  385. AsyncTaskChain *chain = _task_chains[i];
  386. chain->do_stop_threads();
  387. }
  388. }
  389. ////////////////////////////////////////////////////////////////////
  390. // Function: AsyncTaskManager::start_threads
  391. // Access: Published
  392. // Description: Starts any requested threads to service the tasks on
  393. // the queue. This is normally not necessary, since
  394. // adding a task will start the threads automatically.
  395. ////////////////////////////////////////////////////////////////////
  396. void AsyncTaskManager::
  397. start_threads() {
  398. MutexHolder holder(_lock);
  399. // We iterate through with an index, rather than with an iterator,
  400. // because it's possible for a task to adjust the task_chain list
  401. // during its execution.
  402. for (unsigned int i = 0; i < _task_chains.size(); ++i) {
  403. AsyncTaskChain *chain = _task_chains[i];
  404. chain->do_start_threads();
  405. }
  406. }
  407. ////////////////////////////////////////////////////////////////////
  408. // Function: AsyncTaskManager::get_tasks
  409. // Access: Published
  410. // Description: Returns the set of tasks that are active or sleeping
  411. // on the task manager, at the time of the call.
  412. ////////////////////////////////////////////////////////////////////
  413. AsyncTaskCollection AsyncTaskManager::
  414. get_tasks() const {
  415. MutexHolder holder(_lock);
  416. AsyncTaskCollection result;
  417. TaskChains::const_iterator tci;
  418. for (tci = _task_chains.begin();
  419. tci != _task_chains.end();
  420. ++tci) {
  421. AsyncTaskChain *chain = (*tci);
  422. result.add_tasks_from(chain->do_get_active_tasks());
  423. result.add_tasks_from(chain->do_get_sleeping_tasks());
  424. }
  425. return result;
  426. }
  427. ////////////////////////////////////////////////////////////////////
  428. // Function: AsyncTaskManager::get_active_tasks
  429. // Access: Published
  430. // Description: Returns the set of tasks that are active (and not
  431. // sleeping) on the task manager, at the time of the
  432. // call.
  433. ////////////////////////////////////////////////////////////////////
  434. AsyncTaskCollection AsyncTaskManager::
  435. get_active_tasks() const {
  436. MutexHolder holder(_lock);
  437. AsyncTaskCollection result;
  438. TaskChains::const_iterator tci;
  439. for (tci = _task_chains.begin();
  440. tci != _task_chains.end();
  441. ++tci) {
  442. AsyncTaskChain *chain = (*tci);
  443. result.add_tasks_from(chain->do_get_active_tasks());
  444. }
  445. return result;
  446. }
  447. ////////////////////////////////////////////////////////////////////
  448. // Function: AsyncTaskManager::get_sleeping_tasks
  449. // Access: Published
  450. // Description: Returns the set of tasks that are sleeping (and not
  451. // active) on the task manager, at the time of the
  452. // call.
  453. ////////////////////////////////////////////////////////////////////
  454. AsyncTaskCollection AsyncTaskManager::
  455. get_sleeping_tasks() const {
  456. MutexHolder holder(_lock);
  457. AsyncTaskCollection result;
  458. TaskChains::const_iterator tci;
  459. for (tci = _task_chains.begin();
  460. tci != _task_chains.end();
  461. ++tci) {
  462. AsyncTaskChain *chain = (*tci);
  463. result.add_tasks_from(chain->do_get_sleeping_tasks());
  464. }
  465. return result;
  466. }
  467. ////////////////////////////////////////////////////////////////////
  468. // Function: AsyncTaskManager::poll
  469. // Access: Published
  470. // Description: Runs through all the tasks in the task list, once, if
  471. // the task manager is running in single-threaded mode
  472. // (no threads available). This method does nothing in
  473. // threaded mode, so it may safely be called in either
  474. // case.
  475. ////////////////////////////////////////////////////////////////////
  476. void AsyncTaskManager::
  477. poll() {
  478. MutexHolder holder(_lock);
  479. // We iterate through with an index, rather than with an iterator,
  480. // because it's possible for a task to adjust the task_chain list
  481. // during its execution.
  482. for (unsigned int i = 0; i < _task_chains.size(); ++i) {
  483. AsyncTaskChain *chain = _task_chains[i];
  484. chain->do_poll();
  485. }
  486. // Just in case the clock was ticked explicitly by one of our
  487. // polling chains.
  488. _frame_cvar.notify_all();
  489. }
  490. ////////////////////////////////////////////////////////////////////
  491. // Function: AsyncTaskManager::get_next_wake_time
  492. // Access: Published
  493. // Description: Returns the scheduled time (on the manager's clock)
  494. // of the next sleeping task, on any task chain, to
  495. // awaken. Returns -1 if there are no sleeping tasks.
  496. ////////////////////////////////////////////////////////////////////
  497. double AsyncTaskManager::
  498. get_next_wake_time() const {
  499. MutexHolder holder(_lock);
  500. bool got_any = false;
  501. double next_wake_time = -1.0;
  502. TaskChains::const_iterator tci;
  503. for (tci = _task_chains.begin();
  504. tci != _task_chains.end();
  505. ++tci) {
  506. AsyncTaskChain *chain = (*tci);
  507. double time = chain->do_get_next_wake_time();
  508. if (time >= 0.0) {
  509. if (!got_any) {
  510. got_any = true;
  511. next_wake_time = time;
  512. } else {
  513. next_wake_time = min(time, next_wake_time);
  514. }
  515. }
  516. }
  517. return next_wake_time;
  518. }
  519. ////////////////////////////////////////////////////////////////////
  520. // Function: AsyncTaskManager::output
  521. // Access: Published, Virtual
  522. // Description:
  523. ////////////////////////////////////////////////////////////////////
  524. void AsyncTaskManager::
  525. output(ostream &out) const {
  526. MutexHolder holder(_lock);
  527. do_output(out);
  528. }
  529. ////////////////////////////////////////////////////////////////////
  530. // Function: AsyncTaskManager::write
  531. // Access: Published, Virtual
  532. // Description:
  533. ////////////////////////////////////////////////////////////////////
  534. void AsyncTaskManager::
  535. write(ostream &out, int indent_level) const {
  536. MutexHolder holder(_lock);
  537. indent(out, indent_level)
  538. << get_type() << " " << get_name() << "\n";
  539. TaskChains::const_iterator tci;
  540. for (tci = _task_chains.begin();
  541. tci != _task_chains.end();
  542. ++tci) {
  543. AsyncTaskChain *chain = (*tci);
  544. if (chain->_num_tasks != 0) {
  545. out << "\n";
  546. chain->do_write(out, indent_level + 2);
  547. }
  548. }
  549. }
  550. ////////////////////////////////////////////////////////////////////
  551. // Function: AsyncTaskManager::do_make_task_chain
  552. // Access: Protected
  553. // Description: Creates a new AsyncTaskChain of the indicated name
  554. // and stores it within the AsyncTaskManager. If a task
  555. // chain with this name already exists, returns it
  556. // instead.
  557. //
  558. // Assumes the lock is held.
  559. ////////////////////////////////////////////////////////////////////
  560. AsyncTaskChain *AsyncTaskManager::
  561. do_make_task_chain(const string &name) {
  562. PT(AsyncTaskChain) chain = new AsyncTaskChain(this, name);
  563. TaskChains::const_iterator tci = _task_chains.insert(chain).first;
  564. return (*tci);
  565. }
  566. ////////////////////////////////////////////////////////////////////
  567. // Function: AsyncTaskManager::do_find_task_chain
  568. // Access: Protected
  569. // Description: Searches a new AsyncTaskChain of the indicated name
  570. // and returns it if it exists, or NULL otherwise.
  571. //
  572. // Assumes the lock is held.
  573. ////////////////////////////////////////////////////////////////////
  574. AsyncTaskChain *AsyncTaskManager::
  575. do_find_task_chain(const string &name) {
  576. PT(AsyncTaskChain) chain = new AsyncTaskChain(this, name);
  577. TaskChains::const_iterator tci = _task_chains.find(chain);
  578. if (tci != _task_chains.end()) {
  579. return (*tci);
  580. }
  581. return NULL;
  582. }
  583. ////////////////////////////////////////////////////////////////////
  584. // Function: AsyncTaskManager::remove_task_by_name
  585. // Access: Protected
  586. // Description: Removes the task from the _tasks_by_name index, if it
  587. // has a nonempty name.
  588. ////////////////////////////////////////////////////////////////////
  589. void AsyncTaskManager::
  590. remove_task_by_name(AsyncTask *task) {
  591. if (!task->get_name().empty()) {
  592. // We have to scan linearly through all of the tasks with the same
  593. // name.
  594. TasksByName::iterator tbni = _tasks_by_name.lower_bound(task);
  595. while (tbni != _tasks_by_name.end()) {
  596. if ((*tbni) == task) {
  597. _tasks_by_name.erase(tbni);
  598. return;
  599. }
  600. if ((*tbni)->get_name() != task->get_name()) {
  601. // Too far.
  602. break;
  603. }
  604. ++tbni;
  605. }
  606. // For some reason, the task wasn't on the index.
  607. nassertv(false);
  608. }
  609. }
  610. ////////////////////////////////////////////////////////////////////
  611. // Function: AsyncTaskManager::do_has_task
  612. // Access: Protected
  613. // Description: Returns true if the task is on one of the task lists,
  614. // false if it is not (false may mean that the task is
  615. // currently being serviced). Assumes the lock is
  616. // currently held.
  617. ////////////////////////////////////////////////////////////////////
  618. bool AsyncTaskManager::
  619. do_has_task(AsyncTask *task) const {
  620. TaskChains::const_iterator tci;
  621. for (tci = _task_chains.begin();
  622. tci != _task_chains.end();
  623. ++tci) {
  624. AsyncTaskChain *chain = (*tci);
  625. if (chain->do_has_task(task)) {
  626. return true;
  627. }
  628. }
  629. return false;
  630. }
  631. ////////////////////////////////////////////////////////////////////
  632. // Function: AsyncTaskManager::do_output
  633. // Access: Protected, Virtual
  634. // Description:
  635. ////////////////////////////////////////////////////////////////////
  636. void AsyncTaskManager::
  637. do_output(ostream &out) const {
  638. out << get_type() << " " << get_name()
  639. << "; " << _num_tasks << " tasks";
  640. }
  641. ////////////////////////////////////////////////////////////////////
  642. // Function: AsyncTaskManager::make_global_ptr
  643. // Access: Private, Static
  644. // Description: Called once per application to create the global
  645. // task manager object.
  646. ////////////////////////////////////////////////////////////////////
  647. void AsyncTaskManager::
  648. make_global_ptr() {
  649. nassertv(_global_ptr == (AsyncTaskManager *)NULL);
  650. _global_ptr = new AsyncTaskManager("TaskManager");
  651. _global_ptr->ref();
  652. }
  653. #ifdef __EMSCRIPTEN__
  654. extern "C" void task_manager_poll();
  655. void task_manager_poll() {
  656. AsyncTaskManager *mgr = AsyncTaskManager::get_global_ptr();
  657. nassertv_always(mgr != NULL);
  658. mgr->poll();
  659. }
  660. #endif