Scope
DisplayController_p.h
1 #pragma once
2 
3 #include "DisplayController.h"
4 #include "BaseController_p.h"
5 #include "helpers/SyncQueues.h"
6 #include "parameters/Scope.h"
7 #include "helpers/ScopeMultiImage.h"
8 #include "helpers/ScopeMultiImageResonanceSW.h"
9 #include "ScopeDatatypes.h"
10 #include "gui/ChannelFrame.h"
11 #include "gui/HistogramFrame.h"
12 #include "ScopeLogger.h"
13 
14 namespace scope {
15 
20  : public BaseController<1>::Impl {
21 
22 protected:
25 
28 
30  std::array<std::vector<gui::CChannelFrame* const>, SCOPE_NAREAS> channelframes;
31 
33  mutable std::array<std::mutex, SCOPE_NAREAS> channelframes_mutexe;
34 
36  std::array<std::vector<gui::CHistogramFrame* const>, SCOPE_NAREAS> histogramframes;
37 
39  mutable std::array<std::mutex, SCOPE_NAREAS> histogramframes_mutexe;
40 
41 protected:
43  Impl(const Impl& i);
44 
46  Impl operator=(const Impl& i);
47 
53  ControllerReturnStatus Run(StopCondition* const sc, const uint32_t& _area) override {
54  DBOUT(L"DisplayController::Impl::Run beginning\n");
55  uint32_t area = 0;
56  SCOPE_MULTIIMAGEPTR_T current_frame;
57  ControllerReturnStatus returnstatus(ControllerReturnStatus::none);
58  std::array<uint32_t, SCOPE_NAREAS> framecounts;
59  std::fill(std::begin(framecounts), std::end(framecounts), 0);
60  // avoid the mutexed access to parameters later on
61  DaqMode requested_mode = parameters.requested_mode();
62  std::array<uint32_t, SCOPE_NAREAS> requested_frames;
63 
64  // Initialize (deferred) locks
65  std::array<std::unique_lock<std::mutex>, SCOPE_NAREAS> channelframes_locks;
66  std::array<std::unique_lock<std::mutex>, SCOPE_NAREAS> histogramframes_locks;
67  for ( uint32_t a = 0 ; a < SCOPE_NAREAS ; a++ ) {
68  requested_frames[a] = parameters.areas[a]->daq.requested_frames();
69  channelframes_locks[a] = std::unique_lock<std::mutex>(channelframes_mutexe[a],std::defer_lock);
70  histogramframes_locks[a] = std::unique_lock<std::mutex>(histogramframes_mutexe[a],std::defer_lock);
71  }
72 
73  // Send current run state to channel frames
75 
76  // Dequeue and distribute loop
77  while ( !sc->IsSet() ) {
78  // Dequeue
79  ScopeMessage<SCOPE_MULTIIMAGEPTR_T> msg(input_queue->Dequeue());
80 
81  // If message has abort tag, break from while loop
82  if ( msg.tag == ScopeMessageTag::abort ) {
83  returnstatus = ControllerReturnStatus::stopped;
84  break;
85  }
86 
87  current_frame = msg.cargo;
88  area = current_frame->Area();
89 
90  // Increase framecount if a complete frame was received
91  if ( current_frame->IsCompleteFrame() && current_frame->IsCompleteAvg() ) {
92  framecounts[area]++;
93  DBOUT(L"DisplayController framecount area " << area << L": " << framecounts[area]);
94  }
95 
96  // Distribute current_frame to attached CChannelFrames and render the stuff in CChannelFrame's Active's thread
97  channelframes_locks[area].lock();
98  for ( auto cframe : channelframes[area] )
99  cframe->LayOverAndRender(current_frame);
100  channelframes_locks[area].unlock();
101 
102  // Distribute current_frame to attached CHistogramFrame and calculate and render stuff in CHistogramFrame's Active's thread
103  // (only for complete frames so save time)
104  if ( current_frame->IsCompleteFrame() ) {
105  histogramframes_locks[area].lock();
106  for ( auto hframe : histogramframes[area] )
107  hframe->HistoGramAndRender(current_frame);
108  histogramframes_locks[area].unlock();
109  }
110 
111  // Check if in nframes mode if we have already distributed all requested frames for all areas to display
112  if ( (requested_mode == DaqModeHelper::nframes)
113  && (std::equal(std::begin(requested_frames), std::end(requested_frames), std::begin(framecounts))) ) {
114  // if yes we want to stop
115  sc->Set(true);
116  returnstatus = ControllerReturnStatus::finished;
117  DBOUT(L"DisplayController::Impl::Run - all requested frames from all areas processed\n");
118  }
119  }
120 
121  if ( sc->IsSet() )
122  returnstatus = ControllerReturnStatus(returnstatus || ControllerReturnStatus::stopped);
123 
124  UpdateStatusInFrames(RunStateHelper::Stopped);
125  DBOUT(L"DisplayController::Impl::Run ended\n");
126  return returnstatus;
127  }
128 
130  void UpdateStatusInFrames(const RunState& _rs) {
131  for ( uint32_t a = 0 ; a < SCOPE_NAREAS ; a++ ) {
132  std::lock_guard<std::mutex> lockc(channelframes_mutexe[a]);
133  for( auto cframe : channelframes[a] )
134  cframe->UpdateStatus(_rs);
135  std::lock_guard<std::mutex> lockh(histogramframes_mutexe[a]);
136  for( auto hframe : histogramframes[a] )
137  hframe->UpdateStatus(_rs);
138  }
139  }
140 
141 public:
144  : BaseController::Impl(_parameters)
145  , input_queue(_iqueue) {
146  DBOUT(L"DisplayController::Impl::Impl");
147  }
148 
150  virtual ~Impl() {
151  DBOUT(L"DisplayController::Impl::~Impl");
152  StopAll();
153  WaitForAll(-1);
154  }
155 
159  void StopOne(const uint32_t& _a) override {
161  ScopeMessage<SCOPE_MULTIIMAGEPTR_T> stopmsg(ScopeMessageTag::abort, nullptr);
162  input_queue->Enqueue(stopmsg);
163  }
164 
168  *parameters.areas[_ap.area()] = _ap; // Update so that we have the current resolution in here
169  // Clear the queue, so we don't have frames with the (now) wrong resolution
170  input_queue->Clear();
171  DBOUT(L"DisplayController::Impl::ResolutionChange to " << parameters.areas[_ap.area()]->Currentframe().xres() << L" " << parameters.areas[_ap.area()]->Currentframe().yres());
172  }
173 
177  void SetHistogramLimits(const uint32_t& _area, const uint32_t& _channel, const uint16_t& _lower, const uint16_t& _upper) {
178  std::lock_guard<std::mutex> lock(channelframes_mutexe[_area]);
179  for ( auto cframe : channelframes[_area] )
180  cframe->SetHistogramLimits(_channel, _lower, _upper);
181  }
182 
185  void AttachFrame(gui::CChannelFrame* const _cframe) {
186  uint32_t area = _cframe->Area();
187  std::lock_guard<std::mutex> lock(channelframes_mutexe[area]);
188  channelframes[area].push_back(_cframe);
189  _cframe->UpdateStatus(parameters.run_state());
190  }
191 
195  void DetachFrame(gui::CChannelFrame* const _cframe) {
196  uint32_t area = _cframe->Area();
197  std::lock_guard<std::mutex> lock(channelframes_mutexe[area]);
198  std::vector<gui::CChannelFrame* const>::iterator found
199  = std::find_if(std::begin(channelframes[area]), std::end(channelframes[area]), [&](const gui::CChannelFrame* const f)
200  { return f->m_hWnd == _cframe->m_hWnd; } );
201  if ( found == std::end(channelframes[area]) )
202  throw std::exception("DisplayController::Impl::DetachChannelFrame no match");
203  else
204  channelframes[area].erase(found);
205  }
206 
209  void AttachFrame(gui::CHistogramFrame* const _hframe) {
210  uint32_t area = _hframe->Area();
211  std::lock_guard<std::mutex> lock(histogramframes_mutexe[area]);
212  histogramframes[area].push_back(_hframe);
213  _hframe->UpdateStatus(parameters.run_state());
214  }
215 
218  bool HistogramAlreadyAttached(const uint32_t& _area) const {
219  std::lock_guard<std::mutex> lock(histogramframes_mutexe[_area]);
220  return (histogramframes[_area].size() > 0);
221  }
222 
226  void DetachFrame(gui::CHistogramFrame* const _hframe) {
227  uint32_t area = _hframe->Area();
228  std::lock_guard<std::mutex> lock(histogramframes_mutexe[area]);
229  std::vector<gui::CHistogramFrame* const>::iterator found
230  = std::find_if(std::begin(histogramframes[area]), std::end(histogramframes[area]), [&](const gui::CHistogramFrame* const f)
231  { return f->m_hWnd == _hframe->m_hWnd; } );
232  if ( found == std::end(histogramframes[area]) )
233  throw std::exception("DisplayController::Impl::DetachHistogramFrame no match");
234  else
235  histogramframes[area].erase(found);
236  }
237 
241 
242  for ( uint32_t a = 0 ; a < SCOPE_NAREAS ; a++ ) {
243  {
244  std::lock_guard<std::mutex> lock(histogramframes_mutexe[a]);
245  for ( const auto& h : histogramframes[a] ) {
246  wndcoll.AddWindow(L"CHistogramFrame", a, h->m_hWnd);
247  }
248  }
249 
250  {
251  std::lock_guard<std::mutex> lock(channelframes_mutexe[a]);
252  for ( const auto& c : channelframes[a] ) {
253  wndcoll.AddWindow(L"CChannelFrame", a, c->m_hWnd);
254  }
255  }
256  }
257  return wndcoll;
258  }
259 };
260 
261 }
std::array< std::mutex, SCOPE_NAREAS > histogramframes_mutexe
Mutex to protect access to that vector.
Parameters for a whole area (includes a daq and a fpu)
Definition: Scope.h:64
parameters::Scope parameters
the Controller's own set of ScopeParameters
ScopeLogger scope_logger
a ScopeLogger kept handy here
void AttachFrame(gui::CChannelFrame *const _cframe)
Attaches a CChannelFrame as observer to the DisplayController.
Thread-safe lock-free bool to signal a requested stop to the worker function currently executed in th...
Definition: helpers.h:87
The master parameters class.
Definition: Scope.h:204
std::array< std::unique_ptr< Area >, SCOPE_NAREAS > areas
holds AreaParameters for all areas.
Definition: Scope.h:231
void Clear()
Clears the queue.
Definition: SyncQueues.h:37
void StopOne(const uint32_t &_a) override
We need to override here.
void UpdateStatus(const RunState &_rs)
Updates the statusstr and send RunUpdateStatusbar to the Active object.
void AttachFrame(gui::CHistogramFrame *const _hframe)
Attaches a CHistogramFrame as observer to the DisplayController.
std::array< std::mutex, SCOPE_NAREAS > channelframes_mutexe
Mutex to protect access to that vector.
bool HistogramAlreadyAttached(const uint32_t &_area) const
parameters::WindowCollection GetWindowCollection() const
Adds frames to a WindowCollection.
Impl(SynchronizedQueue< ScopeMessage< SCOPE_MULTIIMAGEPTR_T >> *const _iqueue, const parameters::Scope _parameters)
Connects queue and gets parameters.
Base class for all Scope datatypes here, provides a uniform interface (and saves typing...).
void Enqueue(const T &elem)
Enqueues an element and notifies one waiting operation that queue is not empty.
Definition: SyncQueues.h:43
Manages the display of images.
Definition: ChannelFrame.h:26
void AddWindow(const std::wstring &_type, const uint32_t &_area, HWND _hwnd)
Add a window to the collection.
Definition: Windows.cpp:38
The implementation class of the DisplayController.
A logger class to log various messages and user comments.
Definition: ScopeLogger.h:24
ScopeValue< DaqMode > requested_mode
requested acquisition mode (see DaqModeHelper)
Definition: Scope.h:279
Impl operator=(const Impl &i)
disable assignment
ControllerReturnStatus Run(StopCondition *const sc, const uint32_t &_area) override
Main function for managing display.
T cargo
the cargo
Definition: helpers.h:72
In here all declarations for all kinds of datatypes Scope needs.
void ResolutionChange(const parameters::Area &_ap)
Go through all CChannelFrames and request resize to cope with new image size.
virtual ControllerReturnStatus WaitForAll(const int32_t &_wait_time)
Wait for the futures of all async worker functions.
virtual void StopAll()
Request all async worker function to stop.
virtual void StopOne(const uint32_t &_a)
Request one async worker function to stop by settings its StopCondition to true.
#define DBOUT(s)
A debug output to the debug console.
Definition: helpers.h:153
Manages the display of histograms.
std::array< std::vector< gui::CChannelFrame *const >, SCOPE_NAREAS > channelframes
Vector of CChannelFrame observers.
A synchronized, thread-safe queue was modeled after ringbuffer example from boost?! and/or a Herb Sutter column?!
Definition: DaqController.h:7
ScopeValue< RunState > run_state
current RunState
Definition: Scope.h:276
virtual ~Impl()
Stops and interrupts thread if necessary.
void DetachFrame(gui::CChannelFrame *const _cframe)
Detaches a CChannelFrame as observer from the DisplayController.
void Set(const bool &_a=true)
Definition: helpers.h:108
void DetachFrame(gui::CHistogramFrame *const _hframe)
Detaches a CHistogramFrame as observer from the DisplayController.
ScopeNumber< uint32_t > area
the number of this area
Definition: Scope.h:69
uint32_t Area() const
Definition: ChannelFrame.h:194
Impl(const Impl &i)
disable copy
Parameters for all frames/windows on screen.
Definition: Windows.h:43
std::array< std::vector< gui::CHistogramFrame *const >, SCOPE_NAREAS > histogramframes
Vector of CHistogramFrame observers.
void UpdateStatusInFrames(const RunState &_rs)
Calls CChannelFrame::UpdateStatus and CHistogramFrame::UpdateStatus in all attached frames...
Base class for all controllers.
T Dequeue()
Dequeues front element, waits indefinitely if queue is empty.
Definition: SyncQueues.h:61
virtual void UpdateStatus(const RunState &_rs)
Updates the statusstr and send RunUpdateStatusbar to the Active object.
SynchronizedQueue< ScopeMessage< SCOPE_MULTIIMAGEPTR_T > > *const input_queue
Input queue with multi images from the PipelineController.
void SetHistogramLimits(const uint32_t &_area, const uint32_t &_channel, const uint16_t &_lower, const uint16_t &_upper)
Go through all CChannelFrames of that area and set the histogram limits there.
bool IsSet() const
Definition: helpers.h:105