Does this text resembles any script language? - printing

According to a laboratory instrument (OS: windows 2000) manufacturer's guidelines , result print format can be edited with an limited set of operators an tags like:
#PATNUM/14 Patient identification number
#PATNAM/33 Patient name
#SSEX/1 Patient sex
#AGE/4 Patient age
#BIRDAT2/8 Date of birth
#SSTTUS/1 Patient status (in or out)
#ADDAD1/31 Patient address
#ADDAD2/31 Second line for the patient address
#CPCOM/5 Patient coded comment
#TPCOM/30 Patient comment
#FILESTS/29 Status of the selected sample
#SELDT/43 Date and time of the selected period
#PAGNUM/4 Keyword generating the page number when the list is printed
# Allows a form feed
! Indicates the vertical and horizontal position of the tests and results.
> Indicates the beginning of the next result character string. Do not use it if you want one test per line.
* Indicates the beginning of the patient and sample information area (mandatory entry).
** Indicates the beginning of the result area (mandatory entry).
*** Indicates the beginning of the page bottom (mandatory entry).
and a sample format can be like:
TEST RESULT ABN NORMALS UNITS
*RESCOM
WBC #WBC ( #LOW.- #HIGH ) #UNITS....
RBC #RBC ( #LOW.- #HIGH ) #UNITS....
HGB #HGB ( #LOW.- #HIGH ) #UNITS....
HCT #HCT ( #LOW.- #HIGH ) #UNITS....
MCV #MCV ( #LOW.- #HIGH ) #UNITS....
MCH #MCH ( #LOW.- #HIGH ) #UNITS....
MCHC #MCHC ( #LOW.- #HIGH ) #UNITS....
CHCM #CHCM ( #LOW.- #HIGH ) #UNITS....
CH #CH ( #LOW.- #HIGH ) #UNITS....
RDW #RDW ( #LOW.- #HIGH ) #UNITS....
HDW #HDW ( #LOW.- #HIGH ) #UNITS....
PLT #PLT ( #LOW.- #HIGH ) #UNITS....
MPV #MPV ( #LOW.- #HIGH ) #UNITS....
%NEUT #%NEUT ( #LOW.- #HIGH ) #UNITS....
%LYMPH #%LYMPH ( #LOW.- #HIGH ) #UNITS....
%MONO #%MONO ( #LOW.- #HIGH ) #UNITS....
%EOS #%EOS ( #LOW.- #HIGH ) #UNITS....
%BASO #%BASO ( #LOW.- #HIGH ) #UNITS....
%LUC #%LUC ( #LOW.- #HIGH ) #UNITS....
%NRBC #%NRBC ( #LOW.- #HIGH ) #UNITS....
#NEUT ##NEUT ( #LOW.- #HIGH ) #UNITS....
#LYMPH ##LYMPH ( #LOW.- #HIGH ) #UNITS....
#MONO ##MONO ( #LOW.- #HIGH ) #UNITS....
#EOS ##EOS ( #LOW.- #HIGH ) #UNITS....
#BASO ##BASO ( #LOW.- #HIGH ) #UNITS....
#LUC ##LUC ( #LOW.- #HIGH ) #UNITS....
#NRBC ##NRBC ( #LOW.- #HIGH ) #UNITS....
%RETIC #%RETIC ( #LOW.- #HIGH ) #UNITS....
#RETIC ##RETIC ( #LOW.- #HIGH ) #UNITS....
MCVr #MCVr ( #LOW.- #HIGH ) #UNITS....
CHCMr #CHCMr ( #LOW.- #HIGH ) #UNITS....
CHr #CHr ( #LOW.- #HIGH ) #UNITS....
Instrument printouts are according to this format.
The problem is that I need to have color text in printed results and the instrument instruction manual don't have any useful information in this matter.
I wondered if this script is not instrument specific and is a kind of scripting language I don't know.
Does it looks like any scripting language?

Related

Decrease font size in "nodes near coords" in bar chart #tikzpicture #pgfplots

I was trying to decrease the size of the font in nodes near coords in the following code, but the only solution that I found to avoid the nodes numbers overlap was to decrease their number of decimal digits.
Any suggestions on how to decrease the font of nodes near coords ?
\newcommand{\figureHeight}{0.5625} %% 16:9
\pgfplotsset{
compat = 1.13,
grid = major,
enlarge x limits = 0,
cycle list name = tum,
major grid style = {dotted},
minor grid style = {dotted},
width = \hsize,
%width = \hsize * 0.9,
height = \hsize * 0.9 * \figureHeight,
legend style = { at = {(0.98,0.96)}, anchor = north east,}
}
\begin{figure}[thb]
\centering
\begin{tikzpicture}
\begin{axis}[
ybar = 5pt, % configures `bar shift'
xmajorgrids = false,
x tick label style = {
/pgf/number format/1000 sep =},
xtick = { 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018},
ylabel = Energy Produced in TWh,
enlarge x limits = 0.1,
ymin = 0,
ymax = 125,
bar width = 4pt,
legend style={at={(0.02,0.96)},anchor=north west},
nodes near coords
]
%Hidro
\addplot coordinates { ( 2011 , 18 ) ( 2012 , 21 ) ( 2013 , 23 ) ( 2014 , 19 ) ( 2015 , 19 ) ( 2016 , 21 ) ( 2017 , 20 ) ( 2018 , 19 )};
\addlegendentry{Hydro}
%Biomass
\addplot coordinates { ( 2011 , 34 ) ( 2012 , 40 ) ( 2013 , 41 ) ( 2014 , 43 ) ( 2015 , 44 ) ( 2016 , 45 ) ( 2017 , 45 ) ( 2018 , 45 )};
\addlegendentry{Biomass}
%Wind
\addplot coordinates { ( 2011 , 50 ) ( 2012 , 52 ) ( 2013 , 53 ) ( 2014 , 59 ) ( 2015 , 81 ) ( 2016 , 80 ) ( 2017 , 106 ) ( 2018 , 111 )};
\addlegendentry{Wind}
%Solar
\addplot coordinates { ( 2011 , 20 ) ( 2012 , 26 ) ( 2013 , 31 ) ( 2014 , 36 ) ( 2015 , 40 ) ( 2016 , 38 ) ( 2017 , 39 ) ( 2018 , 46 )};
\addlegendentry{Solar}
\end{axis}
\end{tikzpicture}
\caption{Energy from renewable sources in Germany}
\label{fig:EnergyFromRenewablesGermany}
\end{figure}
You can change the style with nodes near coords style={font=\tiny} (or whatever size you like)
\documentclass{book}
\usepackage{pgfplots}
\newcommand{\figureHeight}{0.5625} %% 16:9
\pgfplotsset{
compat = 1.13,
grid = major,
enlarge x limits = 0,
% cycle list name = tum,
major grid style = {dotted},
minor grid style = {dotted},
width = \hsize,
%width = \hsize * 0.9,
height = \hsize * 0.9 * \figureHeight,
legend style = { at = {(0.98,0.96)}, anchor = north east,},
}
\begin{document}
\begin{figure}[thb]
\centering
\begin{tikzpicture}
\begin{axis}[
ybar = 5pt, % configures `bar shift'
xmajorgrids = false,
x tick label style = {
/pgf/number format/1000 sep =},
xtick = { 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018},
ylabel = Energy Produced in TWh,
enlarge x limits = 0.1,
ymin = 0,
ymax = 125,
bar width = 4pt,
legend style={at={(0.02,0.96)},anchor=north west},
nodes near coords,
nodes near coords style={font=\tiny}
]
%Hidro
\addplot coordinates { ( 2011 , 18 ) ( 2012 , 21 ) ( 2013 , 23 ) ( 2014 , 19 ) ( 2015 , 19 ) ( 2016 , 21 ) ( 2017 , 20 ) ( 2018 , 19 )};
\addlegendentry{Hydro}
%Biomass
\addplot coordinates { ( 2011 , 34 ) ( 2012 , 40 ) ( 2013 , 41 ) ( 2014 , 43 ) ( 2015 , 44 ) ( 2016 , 45 ) ( 2017 , 45 ) ( 2018 , 45 )};
\addlegendentry{Biomass}
%Wind
\addplot coordinates { ( 2011 , 50 ) ( 2012 , 52 ) ( 2013 , 53 ) ( 2014 , 59 ) ( 2015 , 81 ) ( 2016 , 80 ) ( 2017 , 106 ) ( 2018 , 111 )};
\addlegendentry{Wind}
%Solar
\addplot coordinates { ( 2011 , 20 ) ( 2012 , 26 ) ( 2013 , 31 ) ( 2014 , 36 ) ( 2015 , 40 ) ( 2016 , 38 ) ( 2017 , 39 ) ( 2018 , 46 )};
\addlegendentry{Solar}
\end{axis}
\end{tikzpicture}
\caption{Energy from renewable sources in Germany}
\label{fig:EnergyFromRenewablesGermany}
\end{figure}
\end{document}

Drag and Drop List- method 'call' was called on null

I'm trying to make a drag and drop list using flutter_list_drag_and_drop 0.1.6. I've looked for examples of how to implement it, but there aren't any out yet for this specifically, so much of it has been trial and error. Anyway, when I run the app, it gives me an error when trying to drag one of the MyDraggables for the list view. It's says "Exception caught by gesture", "The following NoSuchMethodError was thrown while handling a gesture: The method 'call' was called on null," "Receiver: null", "Tried calling: call(Instance of 'Offset').
I've tried debugging but can not locate where exactly this is crashing. The feedback for the draggable widget is appearing, but stays stuck in place.
```
Widget _buildDragDrop(double _screenHeight, double _screenWidth){
return DragAndDropList(_nonDelList.getList(),
canBeDraggedTo: (int i, int j) {
print("drag to");
// _nonDelList.changePos(_nonDelList.getTaskAt(i), j);
return true;
},
itemBuilder: (BuildContext _context, Task _t1) {
print('Entered Item Builder');
return _buildTask(_t1, _screenHeight, _screenWidth);
},
onDragFinish: (int i, int j){
print('Drag finished');
_nonDelList.changePos(_nonDelList.getTaskAt(i), j);
print('Drag finished 2');
},
dragElevation: 1.5,
);
}
Widget _buildTask(Task _t, double _screenHeight, double
_screenWidth){
final bool alreadyCompleted = !(_t.getPressed());
return new MyDraggable(
child: new ListTile(
title: new Text(_t.getEntry()),
trailing: new Icon(
alreadyCompleted ? Icons.check_box :
Icons.check_box_outline_blank,
color: alreadyCompleted ? _t.getColor() : Colors.black,
),
subtitle: new Text(_t.getDescription()),
),
onDragStarted: (){
print('Started Drag');
},
onMyDraggableCanceled: (Velocity v, Offset o){
print('Drag Canceled');
},
feedback: Material(
shape: CircleBorder(),
child: new InkResponse(
child: Container(
width: _screenWidth / 15.0,
height: _screenWidth / 15.0,
color: Colors.red,
),
),
),
);
}
```
I would expect the list tile to drag and drop in place. The only thing that is happening however, is my feedback is appearing at the top left of the list tile when I start the drag, and then this error is immediately spit out. Also, 'Started Drag' and 'Drag Canceled' are not print out, the only thing that is printing is 'Entered Item Builder.'
I welcome and appreciate all help!
Thanks in advance!
EDIT (Stacktrace)
I/flutter ( 2974): ══╡ EXCEPTION CAUGHT BY GESTURE ╞═══════════════════════════════════════════════════════════════════
I/flutter ( 2974): The following NoSuchMethodError was thrown while handling a gesture:
I/flutter ( 2974): The method 'call' was called on null.
I/flutter ( 2974): Receiver: null
I/flutter ( 2974): Tried calling: call(Instance of 'Offset')
I/flutter ( 2974):
I/flutter ( 2974): When the exception was thrown, this was the stack:
I/flutter ( 2974): #0 Object.noSuchMethod (dart:core/runtime/libobject_patch.dart:50:5)
I/flutter ( 2974): #1 DragAvatar.updateDrag
package:flutter_list_drag_and_drop/my_draggable.dart:547
I/flutter ( 2974): #2 new DragAvatar
package:flutter_list_drag_and_drop/my_draggable.dart:498
I/flutter ( 2974): #3 MyDraggableState._startDrag
package:flutter_list_drag_and_drop/my_draggable.dart:328
I/flutter ( 2974): #4 MultiDragGestureRecognizer._startDrag.<anonymous closure>
package:flutter/…/gestures/multidrag.dart:263
I/flutter ( 2974): #5 GestureRecognizer.invokeCallback
package:flutter/…/gestures/recognizer.dart:120
I/flutter ( 2974): #6 MultiDragGestureRecognizer._startDrag
package:flutter/…/gestures/multidrag.dart:263
I/flutter ( 2974): #7 MultiDragGestureRecognizer.acceptGesture.<anonymous closure>
package:flutter/…/gestures/multidrag.dart:253
I/flutter ( 2974): #8 _ImmediatePointerState.accepted
package:flutter/…/gestures/multidrag.dart:315
I/flutter ( 2974): #9 MultiDragGestureRecognizer.acceptGesture
package:flutter/…/gestures/multidrag.dart:253
I/flutter ( 2974): #10 GestureArenaManager._resolveInFavorOf
package:flutter/…/gestures/arena.dart:263
I/flutter ( 2974): #11 GestureArenaManager._resolve
package:flutter/…/gestures/arena.dart:222
I/flutter ( 2974): #12 GestureArenaEntry.resolve
package:flutter/…/gestures/arena.dart:52
I/flutter ( 2974): #13 MultiDragPointerState.resolve
package:flutter/…/gestures/multidrag.dart:62
I/flutter ( 2974): #14 _ImmediatePointerState.checkForResolutionAfterMove
package:flutter/…/gestures/multidrag.dart:310
I/flutter ( 2974): #15 MultiDragPointerState._move
package:flutter/…/gestures/multidrag.dart:81
I/flutter ( 2974): #16 MultiDragGestureRecognizer._handleEvent
package:flutter/…/gestures/multidrag.dart:227
I/flutter ( 2974): #17 PointerRouter._dispatch
package:flutter/…/gestures/pointer_router.dart:73
I/flutter ( 2974): #18 PointerRouter.route
package:flutter/…/gestures/pointer_router.dart:101
I/flutter ( 2974): #19 _WidgetsFlutterBinding&BindingBase&GestureBinding.handleEvent
package:flutter/…/gestures/binding.dart:214
I/flutter ( 2974): #20 _WidgetsFlutterBinding&BindingBase&GestureBinding.dispatchEvent
package:flutter/…/gestures/binding.dart:192
I/flutter ( 2974): #21 _WidgetsFlutterBinding&BindingBase&GestureBinding._handlePointerEvent
package:flutter/…/gestures/binding.dart:149
I/flutter ( 2974): #22 _WidgetsFlutterBinding&BindingBase&GestureBinding._flushPointerEventQueue
I/flutter ( 2974): #23 _WidgetsFlutterBinding&BindingBase&GestureBinding._handlePointerDataPacket
package:flutter/…/gestures/binding.dart:85
I/flutter ( 2974): #27 _invoke1 (dart:ui/hooks.dart:223:10)
I/flutter ( 2974): #28 _dispatchPointerDataPacket (dart:ui/hooks.dart:144:5)
I/flutter ( 2974): (elided 3 frames from package dart:async)
I/flutter ( 2974):
I/flutter ( 2974): Handler: onStart
I/flutter ( 2974): Recognizer:
I/flutter ( 2974): ImmediateMultiDragGestureRecognizer#774eb
The stack trace says:
I/flutter ( 2974): When the exception was thrown, this was the stack:
I/flutter ( 2974): #0 Object.noSuchMethod (dart:core/runtime/libobject_patch.dart:50:5)
I/flutter ( 2974): #1 DragAvatar.updateDrag
package:flutter_list_drag_and_drop/my_draggable.dart:547
Okay, so the null pointer exception occurred there. Let's take a look at the code:
onMove(globalPosition);
That fits the error message, which was:
I/flutter ( 2974): Tried calling: call(Instance of 'Offset')
So globalPosition is likely an Offset, and onMove must be an object. Let's search in the code where onMove was supposed to be set:
DragAvatar({
#required this.overlayState,
...
this.onMove,
(line 491)
which (omitting some steps) appears to be obtained from:
const MyDraggable({
Key key,
#required this.child,
#required this.feedback,
...
this.onMove
(line 101)
I don't see anywhere else where onMove is otherwise set. It looks like there's probably a bug that DragAvatar.updateDrag unconditionally calls onMove, that onMove isn't marked #required initially, or that onMove isn't initialized to some default.
At any rate, try supplying an onMove callback when constructing MyDraggable.
(Alternatively, perhaps consider using the official ReorderableListView class, which the flutter_list_drag_and_drop package page even refers to.)

Debugging a fitness calculator with multiple nested IF statements

I'm using the Harris Benedict Equation to calculate people's TDEE. I'm using Google Sheets to create a sort of form for this but Google Sheets is sort of difficult to work with. I'm getting a formula parse error. Formatting is pretty bad sorry about that.
I know I'm making a small comma or parenthesis error somewhere but I'm not sure where.
The code is supposed to ask if people prefer metric/imperial, male/female, height, weight, activity level, and age.
Here's how Google Sheets does if statements. It pretty much is:
IF(A2 = "foo","A2 is foo")
Syntax is:
IF(logical_expression, value_if_true, value_if_false)
=IF (D9=”Imperial”,
IF(D10=”Male”,
IF(D16=”Sedentary (no exercise)”,
66 + ( 6.2 x D14 ) + ( 12.7 x (D13x12+G13) ) – ( 6.76 x D12 )x1.2,
IF(D16=”Lightly Active (1-3 days of exercise/week)”,
66 + ( 6.2 x D14 ) + ( 12.7 x (D13x12+G13) ) – ( 6.76 x D12 )x1.375,
IF(D16=”Moderately Active (3-5 days of exercise/week)”,
66 + ( 6.2 x D14 ) + ( 12.7 x (D13x12+G13) ) – ( 6.76 x D12 )x1.55,
IF(D16=”Very Active(6-7 days of exercise/week)”,
66 + ( 6.2 x D14 ) + ( 12.7 x (D13x12+G13) ) – ( 6.76 x D12 )x1.725,
IF(D16=”Extremely Active(exercise twice a day)”,
66 + ( 6.2 x D14 ) + ( 12.7 x (D13x12+G13) ) – ( 6.76 x D12 )x1.9,
“ “)))))
IF(D16=”Sedentary (no exercise)”,
655.1 + ( 4.35 x D14 ) + ( 4.7 x (D13x12+G13) ) - ( 4.7 x D12 ) x1.2,
IF(Lightly Active (1-3 days of exercise/week)”,
655.1 + ( 4.35 x D14 ) + ( 4.7 x (D13x12+G13) ) - ( 4.7 x D12 ) x1.375,
IF(Moderately Active (3-5 days of exercise/week)”,
655.1 + ( 4.35 x D14 ) + ( 4.7 x (D13x12+G13) ) - ( 4.7 x D12 ) x1.55,
IF(D16=”Very Active(6-7 days of exercise/week)”,
655.1 + ( 4.35 x D14 ) + ( 4.7 x (D13x12+G13) ) - ( 4.7 x D12 ) x1.725,
IF(D16=”Extremely Active(exercise twice a day)”,
655.1 + ( 4.35 x D14 ) + ( 4.7 x (D13x12+G13) ) - ( 4.7 x D12 ) x1.9,
“ “))))))
IF(D10=”Male”,
IF(D16=”Sedentary (no exercise)”,
66.5 + ( 13.75 x D14 ) + ( 5.003 x D13 ) – ( 6.755 x D12 )x1.2,
IF(Lightly Active (1-3 days of exercise/week)”,
66.5 + ( 13.75 x D14 ) + ( 5.003 x D13 ) – ( 6.755 x D12 )x1.375,
IF(Moderately Active (3-5 days of exercise/week)”,
66.5 + ( 13.75 x D14 ) + ( 5.003 x D13 ) – ( 6.755 x D12 )x1.55,
IF(D16=”Very Active(6-7 days of exercise/week)”
66.5 + ( 13.75 x D14 ) + ( 5.003 x D13 ) – ( 6.755 x D12 )x1.725,
IF(D16=”Extremely Active(exercise twice a day)”,
66.5 + ( 13.75 x D14 ) + ( 5.003 x D13 ) – ( 6.755 x D12 )x1.9,
“ “)))))
IF(D16=”Sedentary (no exercise)”,
655.1 + ( 9.563 x D14 ) + ( 1.850 x D13 ) – ( 4.676 x D12 ) x1.2,
IF(Lightly Active (1-3 days of exercise/week)”,
655.1 + ( 9.563 x D14 ) + ( 1.850 x D13 ) – ( 4.676 x D12 ) x1.375,
IF(Moderately Active (3-5 days of exercise/week)”,
655.1 + ( 9.563 x D14 ) + ( 1.850 x D13 ) – ( 4.676 x D12 ) x1.55,
IF(D16=”Very Active(6-7 days of exercise/week)”,
655.1 + ( 9.563 x D14 ) + ( 1.850 x D13 ) – ( 4.676 x D12 ) x1.725,
IF(D16=”Extremely Active(exercise twice a day)”,
655.1 + ( 9.563 x D14 ) + ( 1.850 x D13 ) – ( 4.676 x D12 ) x1.9,
“ “))))))
)
You have things like IF(Lightly Active (1-3 days of exercise/week)” which obviously aren't going to work. This sort of nesting of IFs shouldn't be there in the first place, it's a minefield of typos. Use hlookup or vlookup instead. Example of vlookup replacing five nested IFs:
=if(D9=”Imperial”,
if(D10=”Male”,
vlookup(D16, {
”Sedentary (no exercise)”,
66 + ( 6.2 x D14 ) + ( 12.7 x (D13x12+G13) ) – ( 6.76 x D12 )x1.2;
”Lightly Active (1-3 days of exercise/week)”,
66 + ( 6.2 x D14 ) + ( 12.7 x (D13x12+G13) ) – ( 6.76 x D12 )x1.375;
”Moderately Active (3-5 days of exercise/week)”,
66 + ( 6.2 x D14 ) + ( 12.7 x (D13x12+G13) ) – ( 6.76 x D12 )x1.55;
”Very Active(6-7 days of exercise/week)”,
66 + ( 6.2 x D14 ) + ( 12.7 x (D13x12+G13) ) – ( 6.76 x D12 )x1.725;
”Extremely Active(exercise twice a day)”,
66 + ( 6.2 x D14 ) + ( 12.7 x (D13x12+G13) ) – ( 6.76 x D12 )x1.9,
}, 2, false)
....
Notice that you can put 15 instead of 5 options here, and no new parentheses will be needed.
Depending on how your data is structured, you may be able to put this reference tables elsewhere in the sheet, say in Table!A1:B5, Table!A6:B11, etc:
=if(D9=”Imperial”,
if(D10=”Male”,
vlookup(D16, Table!A1:B5, 2, false),
vlookup(D16, Table!A6:B11, 2, false)
),
if(D10=”Male”,
vlookup(D16, Table!A12:B16, 2, false),
vlookup(D16, Table!A17:B21, 2, false)
)
)
One can wrap each vlookup in iferror so that when the input data is not of expected kind, you get blank output instead of #N/A! error (though the latter is more informative).

how to decode .dSYM file to explicit DWARF format?

DWARF is a debugging information format. The .dSYM file generated by Xcode contain the DWARF debugging information.
The Question is : how to decode the .dSYM file to get the human-readable DWARF information, which should like below.
On Mac OS X, you use the dwarfdump utility to dump the DWARF in .o files or in .dSYM bundles.
% dwarfdump fig7.o
----------------------------------------------------------------------
File: fig7.o (x86_64)
----------------------------------------------------------------------
.debug_info contents:
0x00000000: Compile Unit: length = 0x00000077 version = 0x0002 abbr_offset = 0x00000000 addr_size = 0x08 (next CU at 0x0000007b)
0x0000000b: TAG_compile_unit [1] *
AT_producer( "Apple LLVM version 5.0 (clang-500.2.79) (based on LLVM 3.3svn)" )
AT_language( DW_LANG_C99 )
AT_name( "fig7.c" )
AT_low_pc( 0x0000000000000000 )
AT_stmt_list( 0x00000000 )
AT_comp_dir( "/tmp" )
0x00000026: TAG_base_type [2]
AT_name( "int" )
AT_encoding( DW_ATE_signed )
AT_byte_size( 0x04 )
0x0000002d: TAG_variable [3]
AT_name( "a" )
AT_type( {0x00000026} ( int ) )
AT_external( 0x01 )
AT_decl_file( "/private/tmp/fig7.c" )
AT_decl_line( 1 )
AT_location( [0x0000000000000000] )
0x00000043: TAG_subprogram [4] *
AT_name( "foo" )
AT_decl_file( "/private/tmp/fig7.c" )
AT_decl_line( 2 )
AT_external( 0x01 )
AT_low_pc( 0x0000000000000000 )
AT_high_pc( 0x0000000000000006 )
AT_frame_base( rbp )
0x0000005d: TAG_variable [5]
AT_name( "b" )
AT_decl_file( "/private/tmp/fig7.c" )
AT_decl_line( 4 )
AT_type( {0x00000026} ( int ) )
AT_location( fbreg -4 )
0x0000006b: TAG_variable [5]
AT_name( "c" )
AT_decl_file( "/private/tmp/fig7.c" )
AT_decl_line( 5 )
AT_type( {0x00000026} ( int ) )
AT_location( fbreg -8 )
0x00000079: NULL
0x0000007a: NULL

pthread deadlock issue when using pthread_cond_t

I am having horrible time trying to figure out why my sync. code gets deadlocked when using pthread library. Using winapi primitives is instead of pthread works with no problems. Using c++11 threading also works fine (unless compiled with visual studio 2012 service pack 3, there it just crashes - Microsoft accepted it as a bug.) Using pthread however proves to be a problem - at least running in on linux machine, haven't had a chance to try different OS.
I've written a simple program which illustrates the issue. The code is just showing the deadlock - I am well aware the design is pretty poor and can be written much better.
typedef struct _pthread_event
{
pthread_mutex_t Mutex;
pthread_cond_t Condition;
unsigned char State;
} pthread_event;
void pthread_event_create( pthread_event * ev , unsigned char init_state )
{
pthread_mutex_init( &ev->Mutex , 0 );
pthread_cond_init( &ev->Condition , 0 );
ev->State = init_state;
}
void pthread_event_destroy( pthread_event * ev )
{
pthread_cond_destroy( &ev->Condition );
pthread_mutex_destroy( &ev->Mutex );
}
void pthread_event_set( pthread_event * ev , unsigned char state )
{
pthread_mutex_lock( &ev->Mutex );
ev->State = state;
pthread_mutex_unlock( &ev->Mutex );
pthread_cond_broadcast( &ev->Condition );
}
unsigned char pthread_event_get( pthread_event * ev )
{
unsigned char result;
pthread_mutex_lock( &ev->Mutex );
result = ev->State;
pthread_mutex_unlock( &ev->Mutex );
return result;
}
unsigned char pthread_event_wait( pthread_event * ev , unsigned char state , unsigned int timeout_ms )
{
struct timeval time_now;
struct timespec timeout_time;
unsigned char result;
gettimeofday( &time_now , NULL );
timeout_time.tv_sec = time_now.tv_sec + ( timeout_ms / 1000 );
timeout_time.tv_nsec = time_now.tv_usec * 1000 + ( ( timeout_ms % 1000 ) * 1000000 );
pthread_mutex_lock( &ev->Mutex );
while ( ev->State != state )
if ( ETIMEDOUT == pthread_cond_timedwait( &ev->Condition , &ev->Mutex , &timeout_time ) ) break;
result = ev->State;
pthread_mutex_unlock( &ev->Mutex );
return result;
}
static pthread_t thread_1;
static pthread_t thread_2;
static pthread_event data_ready;
static pthread_event data_needed;
void * thread_fx1( void * c )
{
for ( ; ; )
{
pthread_event_wait( &data_needed , 1 , 90 );
pthread_event_set( &data_needed , 0 );
usleep( 100000 );
pthread_event_set( &data_ready , 1 );
printf( "t1: tick\n" );
}
}
void * thread_fx2( void * c )
{
for ( ; ; )
{
pthread_event_wait( &data_ready , 1 , 50 );
pthread_event_set( &data_ready , 0 );
pthread_event_set( &data_needed , 1 );
usleep( 100000 );
printf( "t2: tick\n" );
}
}
int main( int argc , char * argv[] )
{
pthread_event_create( &data_ready , 0 );
pthread_event_create( &data_needed , 0 );
pthread_create( &thread_1 , NULL , thread_fx1 , 0 );
pthread_create( &thread_2 , NULL , thread_fx2 , 0 );
pthread_join( thread_1 , NULL );
pthread_join( thread_2 , NULL );
pthread_event_destroy( &data_ready );
pthread_event_destroy( &data_needed );
return 0;
}
Basically two threads signaling each other - start doing something, and doing their own thing even if not signaled after a short timeout.
Any idea what it going wrong there?
Thanks.
The problem is the timeout_time parameter to pthread_cond_timedwait(). The way you increment it is eventually and quite soon going to have an invalid value there with nanosecond part bigger than or equal to billion. In this case pthread_cond_timedwait() perhaps return with EINVAL, and probably actually before waiting for the condition.
The problem can be found very quickly with valgrind --tool=helgrind ./test_prog (quite soon it said it had already detected 10000000 errors and gave up counting):
bash$ gcc -Werror -Wall -g test.c -o test -lpthread && valgrind --tool=helgrind ./test
==3035== Helgrind, a thread error detector
==3035== Copyright (C) 2007-2012, and GNU GPL'd, by OpenWorks LLP et al.
==3035== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info
==3035== Command: ./test
==3035==
t1: tick
t2: tick
t2: tick
t1: tick
t2: tick
t1: tick
t1: tick
t2: tick
t1: tick
t2: tick
t1: tick
==3035== ---Thread-Announcement------------------------------------------
==3035==
==3035== Thread #2 was created
==3035== at 0x41843C8: clone (clone.S:110)
==3035==
==3035== ----------------------------------------------------------------
==3035==
==3035== Thread #2's call to pthread_cond_timedwait failed
==3035== with error code 22 (EINVAL: Invalid argument)
==3035== at 0x402DB03: pthread_cond_timedwait_WRK (hg_intercepts.c:784)
==3035== by 0x8048910: pthread_event_wait (test.c:65)
==3035== by 0x8048965: thread_fx1 (test.c:80)
==3035== by 0x402E437: mythread_wrapper (hg_intercepts.c:219)
==3035== by 0x407DD77: start_thread (pthread_create.c:311)
==3035== by 0x41843DD: clone (clone.S:131)
==3035==
t2: tick
==3035==
==3035== More than 10000000 total errors detected. I'm not reporting any more.
==3035== Final error counts will be inaccurate. Go fix your program!
==3035== Rerun with --error-limit=no to disable this cutoff. Note
==3035== that errors may occur in your program without prior warning from
==3035== Valgrind, because errors are no longer being displayed.
==3035==
^C==3035==
==3035== For counts of detected and suppressed errors, rerun with: -v
==3035== Use --history-level=approx or =none to gain increased speed, at
==3035== the cost of reduced accuracy of conflicting-access information
==3035== ERROR SUMMARY: 10000000 errors from 1 contexts (suppressed: 412 from 109)
Killed
There is also two other minor comments:
For improved correctness, in your pthread_event_set() you could have the condition variable broadcast be done before mutex unlock (the effect of wrong ordering basically could break the determinism of the scheduling; helgrind complains about this issue too);
you could safely drop the mutex locking in pthread_event_get() to return the value of ev->State - this should be atomic operation.

Resources