Merge jcorgan/hier developer branch into trunk. Enables creation of true hierarchica...
[debian/gnuradio] / gnuradio-core / src / lib / runtime / gr_runtime_impl.cc
1 /* -*- c++ -*- */
2 /*
3  * Copyright 2006 Free Software Foundation, Inc.
4  *
5  * This file is part of GNU Radio
6  *
7  * GNU Radio is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2, or (at your option)
10  * any later version.
11  *
12  * GNU Radio is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with GNU Radio; see the file COPYING.  If not, write to
19  * the Free Software Foundation, Inc., 51 Franklin Street,
20  * Boston, MA 02110-1301, USA.
21  */
22
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26
27 #define GR_RUNTIME_IMPL_DEBUG 0
28
29 #include <gr_runtime_impl.h>
30 #include <gr_simple_flowgraph.h>
31 #include <gr_hier_block2.h>
32 #include <gr_hier_block2_detail.h>
33 #include <stdexcept>
34 #include <iostream>
35
36 gr_runtime_impl::gr_runtime_impl(gr_hier_block2_sptr top_block) :
37 d_running(false),
38 d_top_block(top_block),
39 d_sfg(gr_make_simple_flowgraph()),
40 d_graphs()
41 {
42 }
43
44 gr_runtime_impl::~gr_runtime_impl()
45 {
46 }
47
48 void
49 gr_runtime_impl::start()
50 {
51     if (d_running)
52         throw std::runtime_error("already running");
53     else
54         d_running = true;
55
56     d_sfg->d_detail->reset();
57     d_top_block->d_detail->flatten(d_sfg);
58     d_sfg->d_detail->validate();
59     d_sfg->d_detail->setup_connections();
60
61     d_graphs = d_sfg->d_detail->partition();
62     if (GR_RUNTIME_IMPL_DEBUG)
63         std::cout << "Flow graph has " << d_graphs.size()
64                   << " sub-graphs." << std::endl;
65
66     d_threads.clear();
67     for (std::vector<gr_block_vector_t>::iterator p = d_graphs.begin();
68          p != d_graphs.end(); p++) {
69         gr_scheduler_thread_sptr thread = gr_make_scheduler_thread(*p);
70         thread->start();
71         d_threads.push_back(thread);
72     }
73 }
74
75 void
76 gr_runtime_impl::stop()
77 {
78     if (!d_running)
79         return;
80
81     for (gr_scheduler_thread_viter_t p = d_threads.begin(); 
82          p != d_threads.end(); p++)
83         (*p)->stop();
84
85     d_running = false;
86 }
87
88 void
89 gr_runtime_impl::wait()
90 {
91     for (gr_scheduler_thread_viter_t p = d_threads.begin(); 
92          p != d_threads.end(); p++) {
93         while(1) {
94             (*p)->join(NULL);
95             if (!(*p)->state() == omni_thread::STATE_TERMINATED)
96                 break;
97         }
98     }
99 }
100
101 gr_scheduler_thread_sptr gr_make_scheduler_thread(gr_block_vector_t graph)
102 {
103     return gr_scheduler_thread_sptr(new gr_scheduler_thread(graph));
104 }
105
106 gr_scheduler_thread::gr_scheduler_thread(gr_block_vector_t graph) :
107     omni_thread(NULL, PRIORITY_NORMAL),
108     d_sts(gr_make_single_threaded_scheduler(graph))
109 {
110 }
111
112 gr_scheduler_thread::~gr_scheduler_thread()
113 {
114 }
115
116 void gr_scheduler_thread::start()
117 {
118     start_undetached();
119 }
120
121 void *gr_scheduler_thread::run_undetached(void *arg)
122 {
123     d_sts->run();
124     return 0;
125 }
126
127 void gr_scheduler_thread::stop()
128 {
129     d_sts->stop();
130 }