rc_process_support.cpp

Go to the documentation of this file.
00001 // vim:set et sts=4 ts=4 tw=75 sw=4 ai ci cin cino=g0,t0:
00002 /*
00003  * Copyright (C) 2007, Technical Computer Science Group,
00004  *                     University of Bonn
00005  *
00006  * This file is part of the ReChannel library.
00007  *
00008  * The ReChannel library is free software; you can redistribute it and/or
00009  * modify it under the terms of the GNU General Public License as
00010  * published by the Free Software Foundation; either version 2 of the
00011  * License, or (at your option) any later version.
00012  *
00013  * This library is distributed in the hope that it will be
00014  * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016  * General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU General Public License
00019  * along with this library; see the file COPYING. If not, write to the
00020  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
00021  * Boston, MA 02110-1301, USA.
00022  *
00023  * Authors: Andreas Raabe and Armin Felke. Implementation by Armin Felke.
00024  *          {raabe, felke}@cs.uni-bonn.de
00025  */
00037 #include "rc_process_support.h"
00038 
00039 namespace ReChannel {
00040 namespace internals {
00041 
00042 process_support::process_info::reset_signal_map
00043     process_support::process_info::p_reset_signal_map;
00044 
00045 const rc_reset_channel_if&
00046 
00047 process_support::process_info::_rc_get_reset_channel(
00048     const sc_signal_in_if<bool>& signal_interface)
00049 {
00050     const rc_reset_channel_if* reset_channel =
00051         dynamic_cast<const rc_reset_channel_if*>(&signal_interface);
00052     if (reset_channel == NULL) {
00053         reset_signal*& signal_ = p_reset_signal_map[&signal_interface];
00054         if (signal_ == NULL) {
00055             signal_ = new reset_signal(
00056                 sc_gen_unique_name("_rc_process_support_reset_signal"));
00057             // (reset_signal will be deleted by SystemC)
00058 
00059             sc_spawn_options opt;
00060             {
00061                 opt.spawn_method();
00062                 opt.set_sensitivity(
00063                     &signal_interface.value_changed_event());
00064             }
00065             sc_spawn(
00066                 sc_bind(
00067                     &process_info::_rc_reset_updater_proc,
00068                     sc_cref(signal_interface), sc_ref(*signal_)),
00069                 sc_gen_unique_name(
00070                     "_rc_process_support_reset_updater_proc"),
00071                 &opt);
00072         }
00073         reset_channel = static_cast<const rc_reset_channel_if*>(signal_);
00074     }
00075     return *reset_channel;
00076 }
00077 
00078 void process_support::process_info::_rc_reset_updater_proc(
00079     const sc_signal_in_if<bool>& from_, reset_signal& to_)
00080 {
00081     to_.write(from_.read());
00082 }
00083 
00084 process_support::process_info::process_info(
00085     boost::function<void (void)> func_,
00086     const rc_process_control& parent_pctrl, bool is_thread_,
00087     bool is_dont_initialize, bool has_sync_reset)
00088     : func(func_), process_control(
00089           parent_pctrl, parent_pctrl.is_active(), has_sync_reset),
00090       p_is_thread(is_thread_), p_is_dont_initialize(false),
00091       p_is_init_run(false)
00092 { }
00093 
00094 process_support::process_info::~process_info()
00095 {
00096     for (int level = 0; level <= 1; ++level) {
00097         reset_channel_vector& vector = p_reset_channels[level];
00098         unsigned int count = vector.size();
00099         for (unsigned int i=0; i < count; ++i) {
00100             process_support::unregister_process_control(
00101                 *vector[i], process_control);
00102         }
00103     }
00104 }
00105 
00106 void process_support::process_info::register_reset_channel(
00107     const rc_reset_channel_if& reset_channel, bool active_level)
00108 {
00109     p_reset_channels[(active_level ? 1 : 0)].push_back(&reset_channel);
00110     process_support::register_process_control(
00111         reset_channel, process_control, active_level);
00112 }
00113 
00114 void process_support::process_info::register_reset_interface(
00115     const sc_signal_in_if<bool>& reset_interface, bool active_level)
00116 {
00117     const rc_reset_channel_if& reset_channel =
00118         process_info::_rc_get_reset_channel(reset_interface);
00119     this->register_reset_channel(reset_channel, active_level);
00120 }
00121 
00122 void process_support::process_info::register_reset_signal(
00123     const sc_signal<bool>& reset_signal, bool active_level)
00124 {
00125     const rc_reset_channel_if& reset_channel =
00126         process_info::_rc_get_reset_channel(reset_signal);
00127     this->register_reset_channel(reset_channel, active_level);
00128 }
00129 
00130 void process_support::process_info::register_reset_port(
00131     const sc_in<bool>& reset_port, bool active_level)
00132 {
00133     const sc_signal_in_if<bool>* const reset_interface =
00134         reset_port.get_interface(0);
00135     if (reset_interface != NULL) {
00136         const rc_reset_channel_if& reset_channel =
00137             process_info::_rc_get_reset_channel(*reset_interface);
00138         this->register_reset_channel(reset_channel, active_level);
00139     } else {
00140         p_reset_ports[(active_level ? 1 : 0)].push_back(&reset_port);
00141     }
00142 }
00143 
00144 void process_support::process_info::register_reset_port_interfaces()
00145 {
00146     for (int level = 0; level <= 1; ++level) {
00147         reset_port_vector& reset_ports = p_reset_ports[level];
00148         const unsigned int count = reset_ports.size();
00149         for (unsigned int i=0; i < count; ++i) {
00150             const sc_in<bool>* const reset_port = reset_ports[i];
00151             if (reset_port->get_interface() != NULL) {
00152                 this->register_reset_port(*reset_port, level);
00153             }
00154         }
00155         reset_ports.clear();
00156     }
00157 }
00158 
00159 void process_support::process_info::update_process_control_state()
00160 {
00161     for (int level = 0; level <= 1; ++level) {
00162         reset_channel_vector& reset_channels = p_reset_channels[level];
00163         const unsigned int count = reset_channels.size();
00164         for (unsigned int i=0; i < count; ++i) {
00165             if (process_support::get_current_level(*reset_channels[i])
00166             == (bool)level) {
00167                 if (process_control.is_active()) {
00168                     process_control.deactivate();
00169                 }
00170                 return;
00171             }
00172         }
00173     }
00174     if (!process_control.is_active()) {
00175         process_control.activate();
00176     }
00177 }
00178 
00179 process_support::process_support()
00180     : sc_prim_channel(sc_gen_unique_name("_rc_process_support")),
00181       p_reconf(
00182           process_support::_rc_find_context(this->get_parent_object())),
00183       p_last_pinfo(NULL), p_last_host(NULL),
00184       p_last_host_child_count(0)
00185 {
00186     // check if process support is used within a resettable module
00187     sc_object* parent = this->get_parent_object();
00188     if (dynamic_cast<sc_module*>(parent) == NULL
00189     || dynamic_cast<rc_resettable*>(parent) == NULL)
00190     {
00191         RC_REPORT_ERROR("RC_ID_INVALID_USAGE_",
00192                 "Resettable processes are only allowed within"
00193                 " resettable modules (in '" << this->name() << "')");
00194     }
00195 
00196     /* ensure that the rc_non_reconfigurable instance exists
00197        before it is used during simulation */
00198     rc_non_reconfigurable::get_instance();
00199 }
00200 
00201 void process_support::declare_process(
00202     const sc_object& host,
00203     const boost::function<void (void)>& declare_proc_callback,
00204     const boost::function<void (void)>& func, sc_sensitive& sensitive,
00205     bool is_thread, bool dont_initialize, bool has_sync_reset)
00206 {
00207     // store the current process object before the creation
00208     sc_object* const proc_obj_before =
00209         sc_get_current_process_handle().get_process_object();
00210 
00211     // suppress 'object name already exists' warning
00212     const sc_actions actions =
00213         sc_report_handler::set_actions(
00214             SC_WARNING, SC_DO_NOTHING);
00215 
00216     // invoke the callback to let it create the process
00217     declare_proc_callback();
00218 
00219     // reset report action
00220     sc_report_handler::set_actions(SC_WARNING, actions);
00221 
00222     sc_object* const proc_obj =
00223         sc_get_current_process_handle().get_process_object();
00224 
00225     // check if process was created correctly by declare_proc_callback()
00226     if (proc_obj == NULL || proc_obj == proc_obj_before) {
00227         // declare_proc_callback() didn't do what was expected from it
00228         RC_REPORT_ERROR(RC_ID_INVALID_USAGE_,
00229             "invalid usage (in '" << this->name() << "')");
00230     }
00231 
00232     const rc_process_control& reconf_pctrl =
00233         p_reconf.rc_get_process_control();
00234 
00235     process_info* const pinfo =
00236         new process_info(
00237             func, reconf_pctrl, is_thread, dont_initialize,
00238             has_sync_reset);
00239     p_reconf_pinfo_map[proc_obj] = pinfo;
00240     p_last_pinfo = pinfo;
00241     p_last_host = &host;
00242     p_last_host_child_count = host.get_child_objects().size();
00243 
00244     sensitive << (pinfo->process_control.get_deactivation_event());
00245 }
00246 
00247 void process_support::method_process()
00248 {
00249     const sc_process_handle curr_proc = sc_get_current_process_handle();
00250     process_info* const pinfo =
00251         this->_rc_find_process_info(curr_proc.get_process_object());
00252 
00253     if (pinfo == NULL || curr_proc.proc_kind() != SC_METHOD_PROC_ )
00254     {
00255         RC_REPORT_ERROR(RC_ID_INVALID_USAGE_,
00256             "invalid usage (in '" << this->name() << "')");
00257     }
00258 
00259     const rc_process_control& reconf_pctrl =
00260         p_reconf.rc_get_process_control();
00261 
00262     rc_process_registry& preg = rc_get_process_registry();
00263     rc_process_handle hproc = preg.get_process_handle(curr_proc, false);
00264     if (!hproc.valid()) {
00265         hproc = preg.register_process(
00266             curr_proc, pinfo->is_dont_initialize(), true,
00267             pinfo->process_control);
00268     }
00269 
00270     if (reconf_pctrl.is_active()) {
00271         if (pinfo->is_init_run() && pinfo->is_dont_initialize()) {
00272             pinfo->set_init_run(false);
00273             // exit normally
00274             return;
00275         }
00276         try {
00277             // call the user method
00278             pinfo->func();
00279             // exit normally
00280             return;
00281         } catch(rc_process_cancel_exception* e) {
00282             delete e; // consume exception
00283         }
00284     }
00285 
00286     if (pinfo->is_dont_initialize()) {
00287         pinfo->set_init_run(true);
00288     }
00289 
00290     ::sc_core::next_trigger(reconf_pctrl.get_activation_event());
00291 }
00292 
00293 void process_support::thread_process()
00294 {
00295     const sc_process_handle curr_proc = sc_get_current_process_handle();
00296     const std::auto_ptr<process_info> pinfo(
00297         this->_rc_fetch_process_info(curr_proc.get_process_object()));
00298 
00299     if (pinfo.get() == NULL || curr_proc.proc_kind() != SC_THREAD_PROC_ )
00300     {
00301         RC_REPORT_ERROR(RC_ID_INVALID_USAGE_,
00302             "invalid usage (in '" << this->name() << "')");
00303     }
00304 
00305     rc_process_registry& preg = rc_get_process_registry();
00306     rc_process_handle hproc = preg.get_process_handle(curr_proc, false);
00307     if (!hproc.valid()) {
00308         hproc = preg.register_process(
00309             curr_proc, pinfo->is_dont_initialize(), true,
00310             pinfo->process_control);
00311     }
00312 
00313     const rc_process_control& reconf_pctrl =
00314         p_reconf.rc_get_process_control();
00315 
00316     pinfo->update_process_control_state();
00317 
00318     bool is_dont_initialize_allowed = false;
00319     while(true)
00320     {
00321         bool has_exited_normally = false;
00322 
00323         if (reconf_pctrl.is_active()) {
00324             try {
00325                 if (is_dont_initialize_allowed
00326                     && pinfo->is_dont_initialize())
00327                 {
00328                     // wait for next trigger
00329                     rc_wait();
00330                 }
00331                 // call the actual process function
00332                 pinfo->func();
00333                 // process exited normally
00334                 has_exited_normally = true;
00335             } catch(rc_process_cancel_exception* e) {
00336                 delete e; // consume exception
00337             }
00338         }
00339 
00340         // has the reconf. been deactivated or has the process terminated?
00341         if (!reconf_pctrl.is_active()
00342         || has_exited_normally
00343         || hproc.terminated())
00344         {
00345             // is process temporary?
00346             if (hproc.is_temporary()) {
00347                 // notify termination event
00348                 hproc.notify_terminated_event();
00349                 // terminate process
00350                 break;
00351             }
00352 
00353             // wait for next activation
00354             hproc.wait_terminated(reconf_pctrl.get_activation_event());
00355             is_dont_initialize_allowed = true;
00356 
00357         } else { // just this process has been reset
00358             if (pinfo->has_sync_reset()) {
00359                 pinfo->update_process_control_state();
00360                 if (!pinfo->process_control.is_active()) {
00361                     ::sc_core::wait();
00362                     pinfo->update_process_control_state();
00363                 }
00364             } else {
00365                 pinfo->process_control.activate();
00366             }
00367             is_dont_initialize_allowed = false;
00368 
00369         }
00370         // restart process...
00371         continue;
00372     }
00373     // terminate physically...
00374 }
00375 
00376 void process_support::dont_initialize(
00377     const sc_object& host) const
00378 {
00379     if (this->has_reconfigurable_context()) {
00380         if (!sc_is_running() && this->_rc_check_valid_last_proc(host)) {
00381             p_last_pinfo->set_dont_initialize(true);
00382         }
00383     }
00384 }
00385 
00386 rc_process_handle process_support::rc_spawn(
00387     boost::function<void (void)> func, const char* name_p,
00388     rc_spawn_options* opt_p)
00389 {
00390     // no function specified?
00391     if (func.empty()) {
00392         RC_REPORT_ERROR(RC_ID_INVALID_USAGE_,
00393             "invalid usage (in '" << this->name() << "')");
00394     }
00395     sc_spawn_options  opt_tmp;
00396     sc_spawn_options* spawn_options;
00397     if (opt_p != NULL) {
00398         spawn_options = static_cast<sc_spawn_options*>(opt_p);
00399     } else {
00400         spawn_options = &opt_tmp;
00401     }
00402 
00403     rc_process_registry& preg = rc_get_process_registry();
00404 
00405     // create the entry point of the reconfigurable process
00406     boost::function<void (void)> entry_func;
00407     if (spawn_options->is_method()) {
00408         entry_func =
00409             boost::bind(&process_support::method_process, this);
00410     } else {
00411         entry_func =
00412             boost::bind(&process_support::thread_process, this);
00413     }
00414 
00415     const rc_process_control& reconf_pctrl =
00416         p_reconf.rc_get_process_control();
00417     bool is_thread = !spawn_options->is_method();
00418     bool dont_initialize = (opt_p != NULL && opt_p->is_dont_initialize());
00419     std::auto_ptr<process_info> pinfo(
00420         new process_info(
00421             func, reconf_pctrl, is_thread, dont_initialize, false));
00422 
00423     if (opt_p != NULL && !opt_p->is_method()) {
00424         rc_spawn_options::reset_port_vector& rpvec =
00425             opt_p->get_reset_port_vector();
00426         for (rc_spawn_options::reset_port_vector::iterator it =
00427                 rpvec.begin(); it != rpvec.end(); ++it)
00428         { pinfo->register_reset_port(*(it->first), it->second); }
00429 
00430         rc_spawn_options::reset_signal_vector& rsvec =
00431             opt_p->get_reset_signal_vector();
00432         for (rc_spawn_options::reset_signal_vector::iterator it =
00433                 rsvec.begin(); it != rsvec.end(); ++it)
00434         { pinfo->register_reset_signal(*(it->first), it->second); }
00435 
00436         rc_spawn_options::reset_channel_vector& rcvec =
00437             opt_p->get_reset_channel_vector();
00438         for (rc_spawn_options::reset_channel_vector::iterator it =
00439                 rcvec.begin(); it != rcvec.end(); ++it)
00440         { pinfo->register_reset_channel(*(it->first), it->second); }
00441 
00442         rc_spawn_options::process_reset_vector& prvec =
00443             opt_p->get_process_reset_vector();
00444         for (rc_spawn_options::process_reset_vector::iterator it =
00445                 prvec.begin(); it != prvec.end(); ++it)
00446         {
00447             pinfo->register_reset_channel(
00448                 static_cast<rc_reset_channel_if&>(*(*it)), true);
00449         }
00450     }
00451 
00452     const rc_process_control& pctrl = pinfo->process_control;
00453     spawn_options->set_sensitivity(&pctrl.get_deactivation_event());
00454 
00455     // suppress 'object name already exists' warning
00456     const sc_actions actions =
00457         sc_report_handler::set_actions(
00458             SC_WARNING, SC_DO_NOTHING);
00459 
00460     // spawn process
00461     const sc_process_handle spawned_process =
00462         sc_spawn(entry_func, name_p, spawn_options);
00463 
00464     // reset report action
00465     sc_report_handler::set_actions(SC_WARNING, actions);
00466 
00467     sc_object* const proc_obj = spawned_process.get_process_object();
00468     p_reconf_pinfo_map[proc_obj] = pinfo.release();
00469 
00470     const bool is_temporary = sc_is_running();
00471     return preg.register_process(
00472         spawned_process, dont_initialize, true, pctrl, is_temporary);
00473 }
00474 
00475 void process_support::terminate()
00476 {
00477     rc_process_handle hproc = rc_get_current_process_handle();
00478     if (!hproc.terminate()) {
00479         sc_object* parent = this->get_parent_object();
00480         RC_REPORT_ERROR(RC_ID_INVALID_USAGE_,
00481             "attempt to terminate non-reconfigurable process (in '"
00482             << (parent ? parent->name() : "(top level)") << "')");
00483     }
00484 }
00485 
00486 bool process_support::reset_signal_is(
00487     const sc_object& host, const sc_in<bool>& reset_port, bool active_level)
00488 {
00489     if (!sc_is_running() && this->_rc_check_valid_last_proc(host)) {
00490         // register port as reset trigger
00491         p_last_pinfo->register_reset_port(reset_port, active_level);
00492         // update child count, it could have changed
00493         p_last_host_child_count = host.get_child_objects().size();
00494         return true;
00495     } else {
00496         return false;
00497     }
00498 }
00499 
00500 
00501 bool process_support::reset_signal_is(
00502     const sc_object& host, const sc_signal<bool>& reset_signal,
00503     bool active_level)
00504 {
00505     if (!sc_is_running() && this->_rc_check_valid_last_proc(host)) {
00506         // register signal as reset trigger
00507         p_last_pinfo->register_reset_signal(reset_signal, active_level);
00508         // update child count, it could have changed
00509         p_last_host_child_count = host.get_child_objects().size();
00510         return true;
00511     } else {
00512         return false;
00513     }
00514 }
00515 
00516 const sc_signal<bool>* process_support::reset_channel_is(
00517     const sc_object& host, rc_reset_channel_if& reset_channel,
00518     bool active_level)
00519 {
00520     const sc_signal<bool>* reset_signal = NULL;
00521     if (!sc_is_running() && this->_rc_check_valid_last_proc(host)) {
00522         // register reset_channel as reset trigger
00523         p_last_pinfo->register_reset_channel(
00524             reset_channel, active_level);
00525     } else {
00526         reset_signal = reset_channel.get_underlying_reset_signal();
00527         if (reset_signal == NULL) {
00528             RC_REPORT_ERROR(RC_ID_INVALID_USAGE_,
00529                 "channel cannot be used as a reset signal for"
00530                 " standard SC_CTHREAD processes"
00531                 " (in '" << host.name() << "')");
00532         }
00533     }
00534     return reset_signal;
00535 }
00536 
00537 void process_support::reset_is(
00538     const sc_object& host, rc_process_reset& process_reset)
00539 {
00540     if (!sc_is_running() && this->_rc_check_valid_last_proc(host)) {
00541         // register process_reset as reset trigger
00542         p_last_pinfo->register_reset_channel(
00543             static_cast<rc_process_reset&>(process_reset), true);
00544     } else {
00545         RC_REPORT_ERROR(RC_ID_INVALID_USAGE_,
00546             "unrelated reset_is() (in '" << host.name() << "')");
00547     }
00548 }
00549 
00550 void process_support::set_sync_reset(const sc_object& host, bool b) const
00551 {
00552     if (!sc_is_running() && this->_rc_check_valid_last_proc(host)) {
00553         if (p_last_pinfo->is_thread()) {
00554             p_last_pinfo->set_sync_reset(b);
00555         } else {
00556             RC_REPORT_WARNING(RC_ID_INVALID_USAGE_,
00557                 "rc_set_" << (b ? "sync" : "async") << "_reset()"
00558                 " has no effect on method processes (in '"
00559                 << host.name() << "')");
00560         }
00561 
00562     } else {
00563         RC_REPORT_WARNING(RC_ID_INVALID_USAGE_,
00564             "unrelated rc_set_" << (b ? "sync" : "async") << "_reset()"
00565             " ignored (in '" << host.name() << "')");
00566     }
00567 }
00568 
00569 rc_process_behavior_change process_support::disable_process_control() const
00570 {
00571     rc_process_handle hproc = rc_get_current_process_handle();
00572     if (this->has_reconfigurable_context() && hproc.is_cancelable()) {
00573         // process is reconfigurable
00574         return hproc.behavior_change(p_reconf.rc_get_process_control());
00575     } else {
00576         // process is considered as non-reconfigurable
00577         return hproc.behavior_change(false);
00578     }
00579 }
00580 
00581 void process_support::before_end_of_elaboration()
00582 {
00583     for (process_info_map::iterator it = p_reconf_pinfo_map.begin();
00584         it != p_reconf_pinfo_map.end();
00585         ++it)
00586     {
00587         it->second->register_reset_port_interfaces();
00588     }
00589 }
00590 
00591 process_support::process_info* process_support::_rc_find_process_info(
00592     sc_object* proc_obj) const
00593 {
00594     process_info_map::const_iterator it =
00595         p_reconf_pinfo_map.find(proc_obj);
00596     return (it != p_reconf_pinfo_map.end() ? it->second : NULL);
00597 }
00598 
00599 process_support::process_info* process_support::_rc_fetch_process_info(
00600     sc_object* proc_obj)
00601 {
00602     process_info_map::iterator it =
00603         p_reconf_pinfo_map.find(proc_obj);
00604     if (it != p_reconf_pinfo_map.end()) {
00605         process_info* const pinfo = it->second;
00606         p_reconf_pinfo_map.erase(it);
00607         return pinfo;
00608     } else {
00609         return NULL;
00610     }
00611 }
00612 
00613 bool process_support::_rc_check_valid_last_proc(
00614     const sc_object& host) const
00615 {
00616     return (p_last_pinfo != NULL
00617         && p_last_host == &host
00618         && host.get_child_objects().size() == p_last_host_child_count);
00619 }
00620 
00621 rc_reconfigurable& process_support::_rc_find_context(
00622     sc_object* start_search)
00623 {
00624     rc_reconfigurable* const context =
00625         rc_get_reconfigurable_context(start_search);
00626 
00627     if (context != NULL) {
00628         return *context;
00629     } else {
00630         return rc_non_reconfigurable::get_instance();
00631     }
00632 }
00633 
00634 } // namespace internals
00635 
00636 rc_process_reset::rc_process_reset()
00637     : sc_prim_channel(sc_gen_unique_name("_rc_process_reset"))
00638     { }
00639 
00640 rc_process_reset::rc_process_reset(const char* name_)
00641     : sc_prim_channel(name_)
00642     { }
00643 
00644 
00645 void rc_process_reset::trigger()
00646 {
00647     rc_process_handle hproc = rc_get_current_process_handle();
00648     bool was_canceled = hproc.is_canceled();
00649 
00650     for (pctrl_set::iterator it = p_pctrl_set.begin();
00651         it != p_pctrl_set.end();
00652         ++it)
00653     {
00654         (*it)->deactivate();
00655     }
00656 
00657     if (hproc.is_canceled()) {
00658         if (!was_canceled) {
00659             sc_core::wait(SC_ZERO_TIME);
00660         }
00661         throw new rc_process_cancel_exception();
00662     }
00663 }
00664 
00665 void rc_process_reset::register_process_control(
00666     rc_process_control& pctrl, bool active_level) const
00667 {
00668     assert(active_level == true);
00669 
00670     if (active_level == true) {
00671         p_pctrl_set.insert(&pctrl);
00672     }
00673 }
00674 
00675 void rc_process_reset::unregister_process_control(
00676     rc_process_control& pctrl) const
00677 {
00678     p_pctrl_set.erase(&pctrl);
00679 }
00680 
00681 } // namespace ReChannel
00682 
00683 //
00684 // $Id: rc_process_support.cpp,v 1.15 2007/12/20 20:37:29 felke Exp $
00685 // $Source: /var/cvs/projekte/ReChannel-v2/src/ReChannel/core/rc_process_support.cpp,v $
00686 //

Generated on Tue Jan 1 23:13:41 2008 for ReChannel by  doxygen 1.5.3