removed is_running method from gr_top_block
[debian/gnuradio] / gnuradio-core / src / lib / runtime / gr_top_block_impl.cc
1 /* -*- c++ -*- */
2 /*
3  * Copyright 2007,2008 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 3, 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 #include <gr_top_block.h>
28 #include <gr_top_block_impl.h>
29 #include <gr_flat_flowgraph.h>
30 #include <gr_scheduler_thread.h>
31 #include <gr_local_sighandler.h>
32
33 #include <stdexcept>
34 #include <iostream>
35 #include <string.h>
36 #include <unistd.h>
37
38 #define GR_TOP_BLOCK_IMPL_DEBUG 0
39
40 gr_top_block_impl::gr_top_block_impl(gr_top_block *owner) 
41   : d_owner(owner),
42     d_running(false),
43     d_ffg(),
44     d_lock_count(0)
45 {
46 }
47
48 gr_top_block_impl::~gr_top_block_impl()
49 {
50   d_owner = 0;
51 }
52
53 void
54 gr_top_block_impl::start()
55 {
56   if (GR_TOP_BLOCK_IMPL_DEBUG)
57     std::cout << "start: entered " << this << std::endl;
58
59   if (d_running)
60     throw std::runtime_error("top_block::start: top block already running or wait() not called after previous stop()");
61
62   if (d_lock_count > 0)
63     throw std::runtime_error("top_block::start: can't call start with flow graph locked");
64
65   // Create new flat flow graph by flattening hierarchy
66   d_ffg = d_owner->flatten();
67
68   // Validate new simple flow graph and wire it up
69   d_ffg->validate();
70   d_ffg->setup_connections();
71
72   // Execute scheduler threads
73   start_threads();
74   d_running = true;
75 }
76
77
78 // N.B. lock() and unlock() cannot be called from a flow graph thread or
79 // deadlock will occur when reconfiguration happens
80 void
81 gr_top_block_impl::lock()
82 {
83   omni_mutex_lock lock(d_reconf);
84   d_lock_count++;
85   if (GR_TOP_BLOCK_IMPL_DEBUG)
86     std::cout << "runtime: locked, count = " << d_lock_count <<  std::endl;
87 }
88
89 void
90 gr_top_block_impl::unlock()
91 {
92   omni_mutex_lock lock(d_reconf);
93   if (d_lock_count <= 0){
94     d_lock_count = 0;           // fix it, then complain
95     throw std::runtime_error("unpaired unlock() call");
96   }
97
98   d_lock_count--;
99   if (GR_TOP_BLOCK_IMPL_DEBUG)
100     std::cout << "unlock: unlocked, count = " << d_lock_count << std::endl;
101
102   if (d_lock_count == 0) {
103     if (GR_TOP_BLOCK_IMPL_DEBUG)
104       std::cout << "unlock: restarting flowgraph" << std::endl;
105     restart();
106   }
107 }
108
109 void
110 gr_top_block_impl::restart()
111 {
112   if (GR_TOP_BLOCK_IMPL_DEBUG)
113     std::cout << "restart: entered" << std::endl;
114
115   if (!d_running)
116     return;             // nothing to do
117
118   // Stop scheduler threads and wait for completion
119   stop();
120   wait();
121   if (GR_TOP_BLOCK_IMPL_DEBUG)
122     std::cout << "restart: threads stopped" << std::endl;
123
124   // Create new simple flow graph
125   gr_flat_flowgraph_sptr new_ffg = d_owner->flatten();        
126   new_ffg->validate();                 // check consistency, sanity, etc
127
128   if (GR_TOP_BLOCK_IMPL_DEBUG) {
129       std::cout << std::endl << "*** Existing flat flowgraph @" << d_ffg << ":" << std::endl;
130       d_ffg->dump();
131   }
132   new_ffg->merge_connections(d_ffg);   // reuse buffers, etc
133
134   if (GR_TOP_BLOCK_IMPL_DEBUG) {
135     std::cout << std::endl << "*** New flat flowgraph after merge @" << new_ffg << ":" << std::endl;
136     new_ffg->dump();
137   }
138   
139   d_ffg = new_ffg;
140
141   start_threads();
142   d_running = true;
143 }
144
145 void
146 gr_top_block_impl::dump()
147 {
148   if (d_ffg)
149     d_ffg->dump();
150 }
151
152 gr_block_vector_t
153 gr_top_block_impl::make_gr_block_vector(gr_basic_block_vector_t blocks)
154 {
155   gr_block_vector_t result;
156   for (gr_basic_block_viter_t p = blocks.begin(); p != blocks.end(); p++) {
157     result.push_back(make_gr_block_sptr(*p));
158   }
159
160   return result;
161 }