threading.cpp
Go to the documentation of this file.
1 
2 #include "example_utils.hpp"
3 
4 #include <mip/definitions/commands_base.hpp>
5 #include <mip/definitions/commands_3dm.hpp>
6 #include <mip/definitions/data_sensor.hpp>
7 
8 #include <thread>
9 #include <chrono>
10 #include <cmath>
11 #include <cstdio>
12 #include <stdexcept>
13 #include <algorithm>
14 
15 const unsigned int maxSamples = 50;
16 volatile unsigned int numSamples = 0;
17 volatile bool stop = false;
18 
19 unsigned int display_progress()
20 {
21  // Display progress.
22 
23  std::printf("Progress: [");
24 
25  unsigned int count = numSamples;
26 
27  // Compute progress as a fraction from 0 to 1 (may exceed 100% if some extra packets get through).
28  float progress = std::min(count / float(maxSamples), 1.0f);
29 
30  unsigned int threshold = std::lround(progress * 50);
31 
32  unsigned int i=0;
33  for(; i<threshold; i++)
34  std::putchar('#');
35  for(; i<50; i++)
36  std::putchar(' ');
37 
38  std::printf("] %.0f%%\r", progress * 100);
39  std::fflush(stdout);
40 
41  return count;
42 }
43 
44 void packet_callback(void*, const mip::PacketRef& packet, mip::Timestamp timestamp)
45 {
46  numSamples++;
47 }
48 
49 void device_thread_loop(mip::DeviceInterface* device)
50 {
51  while(!stop)
52  {
53  if( !device->update(0) )
54  {
55  device->cmdQueue().clear(); // Avoid deadlocks if the socket is closed.
56  break;
57  }
58 
59  std::this_thread::yield();
60  }
61 }
62 
63 bool update_device(mip::DeviceInterface& device, mip::Timeout wait_time)
64 {
65  if( wait_time > 0 )
66  return device.defaultUpdate(wait_time);
67 
68  // Optionally display progress while waiting for command replies.
69  // Displaying it here makes it update more frequently.
70  //display_progress();
71 
72  // Avoid failing the update function as long as the other thread is running.
73  // Doing so may cause a race condition (see comments in mip_interface_wait_for_reply).
74  std::this_thread::sleep_for(std::chrono::milliseconds(5));
75  return true;
76 }
77 
78 #define USE_THREADS 1
79 
80 int main(int argc, const char* argv[])
81 {
82  try
83  {
84  std::unique_ptr<ExampleUtils> utils = handleCommonArgs(argc, argv);
85  std::unique_ptr<mip::DeviceInterface>& device = utils->device;
86 
87  // Disable all streaming channels.
90 
91  // Register a sensor data packet callback.
92  mip::DispatchHandler dispatchHandler;
93  device->registerPacketCallback<&packet_callback>(dispatchHandler, mip::data_sensor::DESCRIPTOR_SET, false);
94 
95  // Set the message format to stream scaled accel at 1/100th the base rate (around a few Hz).
96  mip::DescriptorRate descriptor{ mip::data_sensor::DATA_ACCEL_SCALED, 100 };
97  mip::commands_3dm::writeMessageFormat(*device, mip::data_sensor::DESCRIPTOR_SET, 1, &descriptor);
98 
99 #if USE_THREADS
100  // Set the update function. Before this call, command replies are processed by the main thread.
101  // After this, replies will be processed by the device thread.
102  device->setUpdateFunction<&update_device>();
103 
104  // Start the device thread.
105  std::thread deviceThread( &device_thread_loop, device.get() );
106 #endif // USE_THREADS
107 
108  // Enable streaming.
109  mip::commands_3dm::writeDatastreamControl(*device, mip::data_sensor::DESCRIPTOR_SET, true);
111 
112  unsigned int count = 0;
113  do
114  {
115  count = display_progress();
116 
117  // Ping the device a bunch (stress test).
118  // If setUpdateFunction above is commented out, this can crash the program.
119  for(unsigned int i=0; i<10; i++)
121 
122  } while(count < maxSamples);
123 
124  std::printf("\nDone!\n");
125 
126  // Return the device to idle.
128 
129  stop = true;
130 #if USE_THREADS
131  deviceThread.join();
132 #endif
133  }
134  catch(const std::underflow_error& ex)
135  {
136  return printCommonUsage(argv);
137  }
138  catch(const std::exception& ex)
139  {
140  fprintf(stderr, "Error: %s\n", ex.what());
141  return 1;
142  }
143  return 0;
144 }
packet_callback
void packet_callback(void *, const mip::PacketRef &packet, mip::Timestamp timestamp)
Definition: threading.cpp:44
update_device
bool update_device(mip::DeviceInterface &device, mip::Timeout wait_time)
Definition: threading.cpp:63
stop
volatile bool stop
Definition: threading.cpp:17
device_thread_loop
void device_thread_loop(mip::DeviceInterface *device)
Definition: threading.cpp:49
numSamples
volatile unsigned int numSamples
Definition: threading.cpp:16
printCommonUsage
int printCommonUsage(const char *argv[])
Definition: example_utils.cpp:133
f
f
main
int main(int argc, const char *argv[])
Definition: threading.cpp:80
mip::commands_base::resume
TypedResult< Resume > resume(C::mip_interface &device)
Definition: commands_base.cpp:239
device
mip_interface device
Definition: CV7_example.c:47
handleCommonArgs
std::unique_ptr< ExampleUtils > handleCommonArgs(int argc, const char *argv[], int maxArgs)
Definition: example_utils.cpp:115
mip::commands_3dm::writeDatastreamControl
TypedResult< DatastreamControl > writeDatastreamControl(C::mip_interface &device, uint8_t descSet, bool enable)
Definition: commands_3dm.cpp:1212
maxSamples
const unsigned int maxSamples
Definition: threading.cpp:15
mip::commands_base::ping
TypedResult< Ping > ping(C::mip_interface &device)
Definition: commands_base.cpp:84
display_progress
unsigned int display_progress()
Definition: threading.cpp:19
stderr
stderr
mip::commands_3dm::writeMessageFormat
TypedResult< MessageFormat > writeMessageFormat(C::mip_interface &device, uint8_t descSet, uint8_t numDescriptors, const DescriptorRate *descriptors)
Definition: commands_3dm.cpp:773
mip::commands_base::setIdle
TypedResult< SetIdle > setIdle(C::mip_interface &device)
Definition: commands_base.cpp:99


microstrain_inertial_driver
Author(s): Brian Bingham, Parker Hannifin Corp
autogenerated on Fri May 24 2024 06:48:22