How do I Implement a traffic light state machine in DML? - dml-lang

I am originally a C-developer and I am now getting familiar with DML. I often need to write state machines and I always design them very C-stylish. I suspect that I am not utilizing the DML language to its full extent. Could someone port this traffic light C-implementation to modern DML?
enum TRAFFIC_LIGHT {
RED,
YELLOW,
GREEN,
}
int state;
timer_t timer;
int redTimeMs = 15000;
int greenTimeMs = 10000;
int transitionTimeMs = 1000;
void start_transition_to_green() {
start_timer(transitionTimeMs, tick_to_green);
}
void start_transition_to_red() {
start_timer(transitionTimeMs, tick_to_red);
}
void tick_to_green() {
switch (state) {
case RED:
state = YELLOW;
start_timer(transitionTimeMs, tick_to_green);
break;
case YELLOW:
state = GREEN;
start_timer(transitionTimeMs, tick_to_green);
break;
case GREEN:
start_timer(greenTimeMs, start_transition_to_red);
break;
}
}
void tick_to_red() {
switch (state) {
case GREEN:
state = YELLOW;
start_timer(transitionTimeMs, tick_to_red);
break;
case YELLOW:
state = RED;
start_timer(transitionTimeMs, tick_to_red);
break;
case RED:
start_timer(redTimeMs, start_transition_to_green);
break;
}
}
void main(void) {
state = RED;
start_transition_to_green();
}
I am expecting a DML implementation that is checkpointable.

The easy translation is of "start_timer" to the 'after' construct. This will give you checkpointing of both the "direction" of change (towards green/red) and the time until next change for free.
Enums do not exist (as such) in DML, instead we can define the states as instances of a common template type. Additionally; a template type is serializable so we can store this in a 'saved' variable and obtain the checkpointing for free.
The 'after' can only accepts a delay in cycles or seconds, so I have pre-divided the constants by 1000 and stored them as top-level parameters.
dml 1.4;
device traffic_light;
param desc = "traffic light state machine";
param documentation = "switches red-yellow-green-yellow-red etc...";
// Defines behavior of a traffic light state
// The instantiation if 'name' here is necessary if we want inspection
// as it will put the object name into the template type
template traffic_state is name {
method enter() default {
log info, 2: "Entered %s", name;
current_light_state = this;
}
method tick_to_green();
method tick_to_red();
}
saved traffic_state current_light_state;
param red_time_s = 15;
param green_time_s = 10;
param transition_time_s = 1;
After this, we define each state as a 'group' instantiating our template type. Implementing the correct behavior for ticking into/out-of them.
group red is traffic_state {
method tick_to_red() {
enter();
after red_time_s s: tick_to_green();
}
method tick_to_green() {
after transition_time_s s: yellow.tick_to_green();
}
}
group yellow is traffic_state {
method tick_to_red() {
enter();
after transition_time_s s: red.tick_to_red();
}
method tick_to_green() {
enter();
after transition_time_s s: green.tick_to_green();
}
}
group green is traffic_state {
method tick_to_red() {
after transition_time_s s: yellow.tick_to_red();
}
method tick_to_green() {
enter();
after green_time_s s: tick_to_red();
}
}
Then, we need to start up the chain of 'after' calls exactly once upon creating the device. And additionally since the next after call will be checkpointed we must guard against setting it up again when loading a checkpoint. Using 'SIM_is_restoring_state' on our device object allows us to only execute code while not loading a checkpoint. (note: we need to do this in 'post_init' and not 'init'. This is because the 'queue' attribute that 'after' statements rely on is not yet set on the device object)
method post_init() {
if (!SIM_is_restoring_state(dev.obj)) {
red.enter();
red.tick_to_green();
}
}
Finally, if we want to inspect the state from the simulator we need to expose it as an attribute. Suitably done with a "read-only" (setting state from simulator would be more complicated) and "pseudo" (does not contain state) atribute.
attribute current_light is (pseudo_attr, read_only_attr) {
param type = "s";
method get() -> (attr_value_t) {
return SIM_make_attr_string(current_light_state.name);
}
}

Related

How to access attributes in object dynamically in Raku

I wonder howto access an object's attribute dynamically via a name as a Str at runtime in Raku. Instead of:
#!/usr/bin/rakudo
class c0 {
has $!a0 = 1;
has $!a1 = 2;
method access(Str $m) {
if ($m eq "a0") { return $!a0; }
if ($m eq "a1") { return $!a1; }
}
method set(Str $m, $v) {
if ($m eq "a0") { $!a0 = $v; }
if ($m eq "a1") { $!a1 = $v; }
}
}
my $c = c0.new();
$c.set("a0", 3);
$c.set("a1", 4);
say $c.access("a0");
say $c.access("a1");
I would like to use something that would look in pseudocode:
class c0 {
...
method access(Str $m) {
return self.$m;
}
method set(Str $m, $v) {
self.$m = $v;
}
}
Is this possible in Raku? Which construct do I need to use?
As a backgrounder I was thinking how to implement a role that adds associativity functionality to the class, to transparently access a member. The attribute name would be parametrized: If I have a class class ports { has #!ports_; ... } and an instance my $p = ports.new() then I want to be able to use the subscript syntax to access #ports_ via $p[...] . I try to figure out weather I can define role acc [ Str $member] does Associative[Cool,Str] { ... } and then define ports via class ports does acc["ports_"] { ... }
where the AT-KEY and EXISTS-KEY in role acc are implemented using dynamic attribute access (if that is possible).
I dont want to use "EVAL".
This is possible with some introspection of the attributes. However, I would like to point out that it is the exact intention of private attributes to be private. Creating a workaround to handle them as public attributes is an anti-pattern, and introduces needless complexity.
class c0 {
has $.a0 = 1;
has $.a1 = 2;
method access (Str $m) {
my $attribute = self.^attributes.first({ ~$_ eq '$!' ~ $m });
return unless $attribute;
$attribute.get_value(self); # 1
}
}
my $c = c0.new;
say $c.access('a0');
For setting the value, you can use the .set_value method on the attribute.
method set (Str $m, $v) {
...
$attribute.set_value(self, $v);
}
Old answer left here for historic purposes.
Yes, something like this is possible in Raku. You don't even need to explicitly define the access method.
class c0 {
has $.a0 = 1;
has $a.1 = 2;
}
my $c = $c0.new;
say $c.'a0'(); # 1
This works because Raku creates an accessor method for public variables for your classes, which is called when you use .'a0'(). The () are required for using a quoted method name.
You changed your post to add a question about how to do something like this:
role acc [ Str $member] does Associative[Cool,Str] { ... }
class ports does acc["ports_"] { has #!ports_; ... }
The answer is of course, don't do that.
I mean you can, but you really shouldn't.
I mean you really really shouldn't.
Also you indicate that you want to use [] for indexing.
The thing is that is Positional not Associative.
(I'm ignoring the fact that there is no point to add _ to the end of the attribute name. Usually in Perl or Python adding _ indicated private, but we don't need to do that in Raku.)
The right way to do that is to have the array inside of the role.
role Array::Access [::OF = Cool] does Positional[OF] {
has OF #!array-access handles < AT-POS >;
}
class Ports does Array::Access {
# allows you to access it as self!ports inside of this class
method !ports () is raw { #!array-access }
}
Which shows that adding a role to do that is probably overkill.
class Ports does Positional[Cool] {
has Cool #!ports handles < AT-POS >;
}
If you really, really want to do it they way you asked for, the following works.
role Inner::Array::Access [ Str:D \name, ::OF = Cool ] does Positional[OF] {
# a way to quickly access the attribute
# (hopefully no-one tries to add an attribute of this name to their class)
has $!inner-array handles < AT-POS >;
# set $!inner-array
submethod TWEAK (){
$!inner-array := self.^attributes.first(name).get_value(self);
}
}
class Ports does Inner::Array::Access['#!ports'] {
has #!ports;
# a quick way to add a way to set #!ports for our test
submethod BUILD( :#!ports ){}
}
my Ports $v = ports => [0,10,20,30];
say $v[2]; # 20
Probably what you were thinking is embed the self.^attributes thing into AT‍-‍POS.
role Inner::Array::Access [ Str:D \name, ::OF = Cool ] does Positional[OF] {
method AT-POS ( \index ) is raw {
self.^attributes.first(name).get_value(self).AT-POS(index);
}
}
That would be slow, because it has to do all of those lookups everytime you access a single element.

Return result of Invoking a Delegate from another thread

I've got a GUI with a TabControl. Each new TabPage is created via a new Thread. I want to call this->tabControl->TabCount, but the tabControl is owned by a thread other than the one I'm calling from. Therefore, I need to Invoke a delegate. However, all the examples I find online show printing to std::cout from each of the delegate methods. I need a return value, in this case an int.
delegate int MyDel();
int InvokeTabCount()
{
if (this->InvokeRequired)
{
MyDel^ del = gcnew MyDel(this, &MyTabControl::InvokeTabCount);
auto temp = this->Invoke(del); // can't just "return this->Invoke(del)"
return temp; // Invoke() returns a System::Object^
}
else
{
return this->tabControl->TabCount;
}
}
void CreateNewTab()
{
// do stuff
this->tabControl->TabPages->Insert(InvokeTabCount() - 1, myNewTab); // insert a tab
this->tabControl->SelectTab(InvokeTabCount() - 2); // OutOfBounds and tabPageNew
}
System::Void MethodToAddNewTabPage() //actually a click event but whatever
{
System::Threading::Thread^ newThread =
gcnew System::Threading::Thread(
gcnew System::Threading::ThreadStart(this, &MyTabControl::CreateNewTab));
newThread->Start();
}
Currently, my InvokeTabCount() method is returning -1 when I simply this->Invoke(del) without returning it. And I am unable to return it because my method expects to return an int instead of a System::Object^ which is what Invoke() returns. However, when debugging I find that auto temp contains the value 2 which is correct. And temp->ToString() contains the value "2" which would also be correct.
How do I return this->Invoke(del)?
Do I need to set the value of a global variable from within my InvokeTabCount() method? I suppose I could find a way to translate from System::String^ to std::string to utilize std::stoi(), but that seems like an odd workaround.
Current solution:
delegate int MyDel();
int InvokeTabCount()
{
if (this->InvokeRequired)
{
MyDel^ del = gcnew MyDel(this, &MyTabControl::InvokeTabCount);
auto temp = this->Invoke(del);
return int::Parse(temp->ToString());
}
else
{
return this->tabControl->TabCount;
}
}
The result is an integer, boxed and contained in an Object^ reference. You should be able to simply cast it to int.
If you want to be extra safe, do a null check and verify that temp->GetType() returns int::typeid, but that's probably overkill since you're creating the delegate (still in the typed form) right there.

Call multiple classes without switch-case or if-else

I want to know weather is is possible or not, a way to call different classes on the basis of an integer value without conditional statements like switch case?
What I am having is:
int val = // getting some value here from a method
String data = // getting some value here from a method
switch(val)
{
case 1:
{
new TempClass1(data);
break;
}
case 2:
{
new TempClass2(data);
break;
}
}
What I want is like:
int val = // getting some value here from a method
String data = // getting some value here from a method
new TempClass(val, data);
This should call the object of TempClass1 or TempClass1 as per "val"
Any help will be appreciated.
Maybe use a Factory for the classes, assuming your two classes share a base class named TempBaseClass:
class TempClassFactory {
static public TempBaseClass getTempClass(int val, String data)
{
switch(val)
{
case 1:
{
return new TempClass1(data);
break;
}
case 2:
{
return new TempClass2(data);
break;
}
default:
throw new Exception("Bad value");
}
}
}
int val = // getting some value here from a method
String data = // getting some value here from a method
TempClassFactory::getTempClass(val, data);

E_SCN_READINCOMPATIBLE Notification error thrown while scanning bar code on MC9090G

I'm using EMDK 2.5 (VS2008 and VC# and .NetCF3.5) Barcode2 class from the library to write a sample application to scan bar codes. I followed the samples available in EMDK namely CS_Barcode2Sample1 project.Every time I hardware trigger the scan the notification "E_SCN_READINCOMPATIBLE" is thrown and not able to retrieve the scanned data. The documentation doesn't say much about the cause of E_SCN_READINCOMPATIBLE notification and no luck from Google search. I tried several options including making use of Symbol.Barcode and the outcome is same.
I also tried EMDK 2.3 but the result is same.
I've pasted the whole code here....
public partial class Form1 : Form
{
private Barcode2 myBarcode2 = null;
public Form1()
{
InitializeComponent();
InitBarcode();
}
public bool InitBarcode()
{
// If the Barcode2 object is already initialized then fail the initialization.
if (myBarcode2 != null)
{
return false;
}
else // Else initialize the reader.
{
try
{
Symbol.Barcode2.Device[] AvailableDevices = Symbol.Barcode2.Devices.SupportedDevices;
if (AvailableDevices.Length == 0)
{
return false;
}
if (AvailableDevices.Length == 1)
{
//get the first available scanner in the list
Symbol.Barcode2.Device MyDevice = AvailableDevices[0];
// Create the reader, based on selected device.
myBarcode2 = new Barcode2(MyDevice);
// Attach a scan notification handler.
//this.myScanNotifyHandler = new Barcode2.OnScanHandler(myBarcode2_ScanNotify);
myBarcode2.OnScan += myBarcode2_ScanNotify;
// Attach a status notification handler.
//this.myStatusNotifyHandler = new Barcode2.OnStatusHandler(myBarcode2_StatusNotify);
myBarcode2.OnStatus += myBarcode2_StatusNotify;
myBarcode2.Config.TriggerMode = TRIGGERMODES.HARD;
// Submit a scan.
myBarcode2.Scan(5000);
}
}
catch (OperationFailureException ex)
{
MessageBox.Show("Exception Raised 1");
return false;
}
catch (InvalidRequestException ex)
{
MessageBox.Show("Exception Raised 2");
return false;
}
catch (InvalidIndexerException ex)
{
MessageBox.Show("Exception Raised 3");
return false;
}
}
return false;
}
private void myBarcode2_ScanNotify(ScanDataCollection scanDataCollection)
{
// Checks if the BeginInvoke method is required because the OnScan delegate is called by a different thread
if (this.InvokeRequired)
{
// Executes the OnScan delegate asynchronously on the main thread
this.BeginInvoke(new Barcode2.OnScanHandler(myBarcode2_ScanNotify), new object[] { scanDataCollection });
}
else
{
// Get ScanData
ScanData scanData = scanDataCollection.GetFirst;
int i;
switch (scanData.Result)
{
case Symbol.Barcode2.Results.SUCCESS:
String str = scanData.Text;
myBarcode2.Config.TriggerMode = TRIGGERMODES.HARD;
myBarcode2.Scan(5000);
break;
case Symbol.Barcode2.Results.E_SCN_READTIMEOUT:
break;
case Symbol.Barcode2.Results.CANCELED:
break;
case Symbol.Barcode2.Results.E_SCN_DEVICEFAILURE:
i = 93;
break;
default:
if (scanData.Result == Symbol.Barcode2.Results.E_SCN_READINCOMPATIBLE)
{
// If the failure is E_SCN_READINCOMPATIBLE, exit the application.
MessageBox.Show("Fatal Error");
this.Close();
return;
}
break;
}
}
}
private void myBarcode2_StatusNotify(StatusData statusData)
{
// Checks if the Invoke method is required because the OnStatus delegate is called by a different thread
if (this.InvokeRequired)
{
// Executes the OnStatus delegate on the main thread
this.Invoke(new Barcode2.OnStatusHandler(myBarcode2_StatusNotify), new object[] { statusData });
}
else
{
int i;
switch (statusData.State)
{
case States.IDLE:
break;
case States.READY:
break;
default:
break;
}
}
}
}
}
I've went thru this recently also, as I observed, it probably due to the scanner device is occupied by other application, where the scan request has been queued already, you can go to memory management, and kill the suspect app, and try your app again.
Refer to the Symbol FAQ

Get pressed keys in J2ME with GameCanvas

I would like to get whether (for example) the 3 key is pressed (KEY_NUM3).
I have tried getKeyStates but it only detects the game action keys.
How could I get the states of non-game action keys?
(I have overridden the keyPressed and keyReleased functions of Canvas and storing the key states in an array (I'm using a Vector for storing but I think could store them in an array too, if that's the problem), but this does not seem to be very nice)
in your keypressed use the keyCode passed in like so
protected void keyPressed(int keyCode)
{
//try catch getGameAction as can legally throw an exception
int gameAction = getGameAction(keyCode);
switch(gameAction)
{
case UP:
break;
case DOWN:
break;
case LEFT:
break;
}
switch(keyCode)
{
case KEY_NUM1:
break;
case KEY_NUM2:
break;
case KEY_NUM3;
break;
}
}
I suppose that can be
something like the code below
int key=getKeyStates();
// i mean keyStates();
if((key&down_pressed)!=0)
{
//do movements
}
but can be
if((key & Canvas.key_num3)!=0)
{
//do something
}
//you can set the super() to true in the constructor

Resources