1 /*
2    Copyright (C) 2006 - 2018 by Joerg Hinrichs <joerg.hinrichs@alice-dsl.de>
3    Part of the Battle for Wesnoth Project https://www.wesnoth.org/
4 
5    This program is free software; you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation; either version 2 of the License, or
8    (at your option) any later version.
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY.
11 
12    See the COPYING file for more details.
13 */
14 
15 #include "generic_event.hpp"
16 
17 #include <algorithm>
18 
19 namespace events{
20 
generic_event(const std::string & name)21 generic_event::generic_event(const std::string& name) :
22 	name_(name),
23 	observers_(),
24 	change_handler_(false),
25 	notify_active_(false)
26 {
27 }
28 
attach_handler(observer * obs)29 bool generic_event::attach_handler(observer* obs){
30 	bool handler_attached = false;
31 
32 	//make sure observers are not notified right now
33 	if (!notify_active_){
34 		change_handler_ = true;
35 		try{
36 			std::vector<observer*>::const_iterator it = std::find(observers_.begin(), observers_.end(), obs);
37 			if (it != observers_.end()){
38 				handler_attached = false;
39 			}
40 			else{
41 				observers_.push_back(obs);
42 				handler_attached = true;
43 			}
44 		}
45 		catch (...){
46 			change_handler_ = false;
47 			throw;
48 		}
49 		change_handler_ = false;
50 	}
51 
52 	return handler_attached;
53 }
54 
detach_handler(observer * obs)55 bool generic_event::detach_handler(observer* obs){
56 	bool handler_detached = false;
57 
58 	//make sure observers are not notified right now
59 	if (!notify_active_){
60 		change_handler_ = true;
61 		try{
62 			std::vector<observer*>::iterator it = std::find(observers_.begin(), observers_.end(), obs);
63 			if (it == observers_.end()){
64 				handler_detached = false;
65 			}
66 			else{
67 				observers_.erase(it);
68 				handler_detached = true;
69 			}
70 		}
71 		catch (...){
72 			change_handler_ = false;
73 			throw;
74 		}
75 		change_handler_ = false;
76 	}
77 
78 	return handler_detached;
79 }
80 
notify_observers()81 void generic_event::notify_observers(){
82 	if (!change_handler_){
83 		notify_active_ = true;
84 		try{
85 			for (std::vector<observer*>::const_iterator it = observers_.begin();
86 				it != observers_.end(); ++it){
87 				(*it)->handle_generic_event(name_);
88 			}
89 		}
90 		catch (...){
91 			//reset the flag if event handlers throw exceptions and don't catch them
92 			notify_active_ = false;
93 			throw;
94 		}
95 		notify_active_ = false;
96 	}
97 }
98 
99 } //namespace events
100