For a certain Perl project of mine I need several Perl processes to share some resources, located in a C++ library. (Don't ask, it's not the core of this question, just the context.)
Thus I am trying to delve my way into two "new" fields in this context: IPC::Shareable, and wrapping C++ using SWIG. It seems I am doing something wrong there, and that is what I would like to ask about.
On the C++ side, I wrote a small test class Rectangle with an empty constructor, a set and a size member function.
Then I wrapped the class in a SWIG-generated Perl package example.
On the Perl side, I tried if the SWIG module works as expected:
use example;
my $testrec = new example::Rectangle;
$testrec->set( 6, 7 );
print $testrec->size() . "\n";
This prints "42", as it should.
Then I tried to test my way into using IPC::Shareable. I wrote two Perl scripts, one "server" and one "client", to test the resource sharing.
The "server":
use IPC::Shareable;
use example;
# v_ for variable, g_ for (IPC) glue
my $v_array;
my $v_rect;
my %options = ( create => 'yes', exclusive => 0, mode => 0644, destroy => 'yes' );
tie $v_array, 'IPC::Shareable', 'g_array', { %options } or die;
tie $v_rect, 'IPC::Shareable', 'g_rect', { %options } or die;
$v_array = [ "0" ];
$v_rect = new example::Rectangle;
$v_rect->set( 6, 7 );
while ( 1 ) {
print "server array: " . join( " - ", #$v_array ) . "\n";
print "server rect: " . $v_rect->size() . "\n";
sleep 3;
}
The "client":
use IPC::Shareable;
use example;
# v_ for variable, g_ for (IPC) glue
my $v_array;
my $v_rect;
my %options = ( create => 0, exclusive => 0, mode => 0644, destroy => 0 );
tie $v_array, 'IPC::Shareable', 'g_array', { %options } or die;
tie $v_rect, 'IPC::Shareable', 'g_rect', { %options } or die;
my $count = 0;
while ( 1 ) {
print "client array: " . join( " - ", #$v_array ) . "\n";
print "client rect: " . $v_rect->size() . "\n";
push( #$v_array, ++$count );
$v_rect->set( 3, $count );
sleep 3;
}
Starting first the "server", then the "client", I get this output for the "server":
server array: 0
server rect: 42
server array: 0 - 1
server rect: 42
server array: 0 - 1 - 2
server rect: 42
And this output for the "client":
client array: 0
client rect: 0
client array: 0 - 1
client rect: 3
client array: 0 - 1 - 2
client rect: 6
So apparently, the array reference gets shared allright, but the client doesn't "see" the example::Rectangle of the server, but works on a (zero-initialized) piece of rogue memory, which in turn the server knows nothing about...
I have a suspicion that I have to do something to $v_rect to make this work properly, but I am not solid enough in OO Perl to know what. Anyone to the rescue?
What you are trying to do will not work. You will have to bite the bullet and do some form of message passing instead.
I don't quite remember how exactly SWIG wraps the C(++)-level objects for Perl, but it's most likely the usual, admittedly horrible "pointer in integer slot" strategy. In this setup, it will allocate a C(++) object and store a pointer to it in a Perl scalar. The Perl object will be a blessed reference to this scalar. The C(++) object will be freed explicitly by the destructor of the Perl class when all references to the Perl object have gone away. A more modern technique for this would be something like what the XS::Object::Magic module allows you to do.
But the details of the wrapper aren't even that important. What matters is that the object is opaque to Perl! With ties, IPC::Shareable uses somewhat out-of-fashion and frankly fragile technology anyway. It may or may not work well for your Perl objects. But when you share the Perl object, the C(++) object will NOT be shared. How could it? Perl knows nothing about it. And it can't possibly.
What you should do instead is think about the problem in terms of message passing and serialization. In order to serialize your C(++) objects, you'll want to allow for some cooperation from the C side of things. Have a look at the hooks that the Storable module provides for serializing objects. As far as message passing/queuing goes, I have enjoyed working with ZeroMQ, which gives you a simple socket-like interface.
Related
The following code attempts to react to one Supply and then, based on the content of some message, change its mind and react to messages from a different Supply. It's an attempt to provide similar behavior to Supply.migrate but with a bit more control.
my $c1 = Supplier.new;
my $c2 = Supplier.new;
my $s = supply {
my $currently-listening-to = $c1.Supply;
my $other-var = 'foo';
whenever $currently-listening-to {
say "got: $_";
if .starts-with('3') {
say "listening to something new";
$currently-listening-to = $c2.Supply;
$other-var = 'bar';
say $other-var;
}
}
}
$s.tap;
for ^7 {
$c1.emit: "$_ from \$c1";
$c2.emit: "$_ from \$c2";
}
sleep 10;
If I understand the semantics of supply blocks correctly (highly doubtful!), this block should have exclusive and mutable access to any variables declared inside the supply block. Thus, I expected this to get the first 4 values from $c1 and then switch to $c2. However, it doesn't. Here's the output:
ot: 0 from $c1
got: 1 from $c1
got: 2 from $c1
got: 3 from $c1
listening to something new
bar
got: 4 from $c1
got: 5 from $c1
got: 6 from $c1
As that output shows, changing $other-var worked just as I expected it to, but the attempt to change $currently-listening-to failed (silently).
Is this behavior correct? If so, what am I missing about the semantics of supply blocks/other constructs that explains this behavior? I got the same results with react blocks and when using a Channel instead of a Supply, so the behavior is consistent across several multiple concurrency constructs.
(In the interest of avoiding an X-Y problem, the use case that triggered this question was an attempt implement Erlang-style error handling. To do so, I wanted to have a supervising supply block that listened to its children and could kill/re-launch any children that got into a bad state. But that means listening to the new children – which led directly to the issue described above.)
I tend to consider whenever as the reactive equivalent of for. (It even supports the LAST loop phaser for doing something when the tapped Supply is done, as well as supporting next, last, and redo like an ordinary for loop!) Consider this:
my $x = (1,2,3);
for $x<> {
.say;
$x = (4,5,6);
}
The output is:
1
2
3
Because at the setup stage of a for loop, we obtain an iterator, and then work through that, not reading $x again on each iteration. It's the same with whenever: it taps the Supply and then the body is invoked per emit event.
Thus another whenever is needed to achieve a tap of the next Supply, while simultaneously closing the tap on the current one. When there are just two Supplys under consideration, the easy way to write it is like this:
my $c1 = Supplier.new;
my $c2 = Supplier.new;
my $s = supply {
whenever $c1 {
say "got: $_";
if .starts-with('3') {
say "listening to something new";
# Tap the next Supply...
whenever $c2 {
say "got: $_";
}
# ...and close the tap on the current one.
last;
}
}
}
$s.tap;
for ^7 {
$c1.emit: "$_ from \$c1";
$c2.emit: "$_ from \$c2";
}
Which will produce:
got: 0 from $c1
got: 1 from $c1
got: 2 from $c1
got: 3 from $c1
listening to something new
got: 3 from $c2
got: 4 from $c2
got: 5 from $c2
got: 6 from $c2
(Note that I removed the sleep 10 because there's no need for it; we aren't introducing any concurrency in this example, so everything runs synchronously.)
Clearly, if there were a dozen Supplys to move between then this approach won't scale so well. So how does migrate work? The key missing piece is that we can obtain the Tap handle when working with whenever, and thus we are able to close it from outside of the body of that whenever. This is exactly how migrate works (copied from the standard library, with comments added):
method migrate(Supply:D:) {
supply {
# The Tap of the Supply we are currently emitting values from
my $current;
# Tap the Supply of Supply that we'll migrate between
whenever self -> \inner {
# Make sure we produce a sensible error
X::Supply::Migrate::Needs.new.throw
unless inner ~~ Supply;
# Close the tap on whatever we are currently tapping
$current.close if $current;
# Tap the new thing and store the Tap handle
$current = do whenever inner -> \value {
emit(value);
}
}
}
}
In short: you don't change the target of the whenever, but rather start a new whenever and terminate the previous one.
I have to display some sentences on a screen.
However, the language can change if the user want to, so I do not want but I can do that :
if(language==1)
{
printf("Hello sir");
}
else if(language==2)
{
printf("Hola senor");
}
OR
printf("%s",language == 1 ? "Hello sir" : "Hola senor");
I do not want that because I have a lot of iterations.
Can I use map or enum and change it during code is running, I was thinking about a things like that :
#define MESSAGE_HELLO "Hello sir" OR "Hola senor"
printf("%s",MESSAGE_HELLO);
Do you have an idea ? Can you help me please ?
You can use some internationalization library that might help you. But here I will focus on how one can solve such a problem. Naturally, you need to have a set of languages, a set of message keys and a relationship between message keys and the languages, which would hold the actual message. Let's see some solutions:
Language file
You can store english.txt, etc. which would look like this:
hello_world="Hello World"
goodbye="Good bye"
and some other language, hungarian.txt for example:
hello_world="Heló Világ"
goodbye="Viszontlátásra"
etc.
Now, you can create an array of Map<String, Map<String, String>>, loop the languages, for each language process the corresponding file and fill the map accordingly.
Database
You can store a languages table, a message_keys table and a messages table. The messages table would have a foreign key pointing to languages and another one to message_keys and the actual message would be stored there as well. You could have an API that you could use in order to request items or groups of messages in a certain language.
There are many possible solutions.
In the professional world, I have often used tables (arrays) of phrases. Each slot in the array represents the phrase in another language.
static const char str_hello[] =
{
/* English */ "hello",
/* Spanish */ "hola",
/* German */ "guten tag",
//...
};
This has worked well in embedded systems.
You probably can create two maps for the sentences you want to translate - one map for one language - and then create a pointer to one of the maps. Then use pointer and [] to take sentences you need. Also, the pointer can be changed so that it points to another map at any moment.
Finally, I found a solution that fits with my requirements.
I use a .json file with all sentences and the languages I use.
{
"my-encoding": "UTF-8",
"messages": [
{
"MESS_HELLO": {
"english": "Hello",
"spanish": "Hola"
}
},
{
"MESS_GOODBYE": {
"english": "Bye",
"spanish": "Adios"
}
},
.......
]
}
To use .json file in C++, I included json-c lib in my project.
After loading the json file, I put it in a
std::unordered_map<std::string, std::unordered_map<std::string, std::string>> m_myTable;
With an ID declared in cpp (same as MESS_HELLO or MESS_GOODBYE).
It looks like that :
//"MESS_HELLO" -> { "english" -> "Hello" ; "spanish" -> "Hola" }
//"MESS_GOODBYE" -> { "english" -> "Bye" ; "other_language" -> "mess_in_other_language" ; +++ }
With that type I can do :
Easily add a new message by changing .json file + declaring in code a new ID
Modify the text by only change .json file
Add a new language by adding to .json file + adding several lines in code, but not a big deal.
To display it, I do something like
const auto &text_it = m_myTable.find("MESS_HELLO")
const auto &language_it = text_it->second.find("english");
printf("%s",language_it->second); //print Hello
Of course, it's in functions and well implemented, but I can't tell more about that.
First, I apologize if you feel this is a duplicate. I looked around and found some very similar questions, but I either got lost or it wasn't quite what I think I need and therefore couldn't come up with a proper implementation.
QUESTION:
So I have a txt file that contains entries made by another script (I can edit the format for how these entries are generated if you can suggest a better way to format them):
SR4 Pool2
11/5/2012 13:45
----------
Beginning Wifi_Main().
SR4 Pool2
11/8/2012 8:45
----------
This message is a
multiline message.
SR4 Pool4
11/5/2012 14:45
----------
Beginning Wifi_Main().
SR5 Pool2
11/5/2012 13:48
----------
Beginning Wifi_Main().
And I made a perl script to parse the file:
#!C:\xampp-portable\perl\bin\perl.exe
use strict;
use warnings;
#use Dumper;
use CGI 'param','header';
use Template;
#use Config::Simple;
#Config::Simple->import_from('config.ini', \%cfg);
my $cgh = CGI->new;
my $logs = {};
my $key;
print "Content-type: text/html\n\n";
open LOG, "logs/Pool2.txt" or die $!;
while ( my $line = <LOG> ) {
chomp($line);
}
print $logs;
close LOG;
My goal is to have a hash in the end that looks like this:
$logs = {
SR4 => {
Pool2 => {
{
time => '11/5/2012 13:45',
msg => 'Beginning Wifi_NDIS_Main().',
},
{
time => '11/8/2012 8:45',
msg => 'This message is a multiline message.',
},
},
Pool4 => {
{
time => '11/5/2012 13:45',
msg => 'Beginning Wifi_NDIS_Main().',
},
},
},
SR5 => {
Pool2 => {
{
time => '11/5/2012 13:45',
msg => 'Beginning Wifi_NDIS_Main().',
},
},
},
};
What would be the best way of going about this? Should I change the formatting of the generated logs to make it easier on myself? If you need anymore info, just ask. Thank you in advanced. :)
The format makes no sense. You used a hash at the third level, but you didn't specify keys for the values. I'm assuming it should be an array.
my %logs;
{
local $/ = ""; # "Paragraph mode"
while (<>) {
my #lines = split /\n/;
my ($x, $y) = split ' ', $lines[0];
my $time = $lines[1];
my $msg = join ' ', #lines[3..$#lines];
push #{ $logs{$x}{$y} }, {
time => $time,
msg => $msg,
};
}
}
Should I change the formatting of the generated logs
Your time stamps appear to be ambiguous. In most time zones, an hour of the year is repeated.
If you can possibly output it as XML, reading it in would be embarrasingly easy with XML::Simple
Although Karthik T idea of using XML makes sense, and I would also consider it, I'm not sure if this is the best route. The first problem is putting it in XML format in the first place.
The second is that XML format might not be so easily parsed. Sure, the XML::Simple module will read the whole thing in one swoop, you then have to parse the XML data structure itself.
If you can set the output however you want, make it in a format that's easy to parse. I like using prefix data identifiers. In the following example, each piece of data has it's own identifier. The ER: tells me when I hit the end of record:
DT: 11/5/2012 13:35
SR: SR4
PL: Pool2
MG: Beginning Wifi_Main().
ER:
DT: 1/8/2012 8:45
SR: SR4
PL: Pool2
MG: This message is a
MG: multiline message.
ER:
Parsing this output is straight forward:
my %hash;
while ( $line = <DATA> ) {
chomp $line;
if ( not $line eq "ER:" ) {
my ($key, $value) = split ( ": ", $line );
$hash{$key} .= "$value "; #Note trailing space!
}
else {
clean_up_hash ( \%hash ); #Remove trailing space on all values
create_entry ( \%log, \%hash );
%hash = ();
}
}
I like using classes whenever I start getting complex data structures, and I would probably create a Local::Log class and subclasses to store each layer of the log. However, it's not an absolute necessity and wasn't part of your question. Still, I would use a create_entry subroutine just to keep the logic of figuring out where in your log that entry belongs inside your loop.
NOTE: I append a space after each piece of data. I did this to make the code simpler since some of your messages may take more than one line. There are other ways to handle this, but I was trying to keep the loop as clean as possible and with as few if statements as possible.
My hobby is writing up stuff on a personal wiki site: http://comp-arch.net.
Currently using mediawiki (although I often regret having chosen it, since I need per page access control.)
Often I create pages that define several terms or concepts on the same page. E.g. http://semipublic.comp-arch.net/wiki/Invalidate_before_writing_versus_write_through_is_the_invalidate.
Oftentimes such "A versus B" pages provide the only definitions of A and B. Or at least the only definitions that I have so far gotten around to writing.
Sometimes I will define many more that two topics on the same page.
If I create such an "A vs B" or other paging containing multiple definitions D1, D2, ... DN, I would like to automatically create redirect pages, so that I can say [[A]] or [[B]] or [[D1]] .. [[DN]] in other pages.
At the moment the only way I know of to create such pages is manually. It's hard to keep up.
Furthermore, at the time I create such a page, I would like to provide some page text - typicaly a category.
Here;s another example: variant page names. I often find that I want to create several variants of a page name, all linking to the same place. For example
[[multithreading]],
[[multithreading (MT)]],
[[MT (multithreading)]],
[[MT]]
Please don;t tell me to use piped links. That's NOT what I want!
TWiki has plugins such as
TOPICCREATE automatically create topics or attach files at topic save time
More than that, I remember a twiki plugin, whose name I cannot remember or google up, that included the text of certain subpages within your current opage. You could then edit all of these pages together, and save - and the text would be extracted and distributed as needed. (By the way, if you can remember the name of tghat package, please remind me. It had certain problems, particularly wrt file locking (IIRC it only locked the top file for editing, bot the sub-topics, so you could lose stuff.))
But this last, in combination with parameterized templtes, would be almost everything I need.
Q: does mediawiki have something similar? I can't find it.
I suppose that I can / could should wrote my own robot to perform such actions.
It's possible to do this, although I don't know whether such extensions exist already. If you're not averse to a bit of PHP coding, you could write your own using the ArticleSave and/or ArticleSaveComplete hooks.
Here's an example of an ArticleSaveComplete hook that will create redirects to the page being saved from all section titles on the page:
$wgHooks['ArticleSaveComplete'][] = 'createRedirectsFromSectionTitles';
function createRedirectsFromSectionTitles( &$page, &$user, $text ) {
// do nothing for pages outside the main namespace:
$title = $page->getTitle();
if ( $title->getNamespace() != 0 ) return true;
// extract section titles:
// XXX: this is a very quick and dirty implementation;
// it would be better to call the parser
preg_match_all( '/^(=+)\s*(.*?)\s*\1\s*$/m', $text, $matches );
// create a redirect for each title, unless they exist already:
// (invalid titles and titles outside ns 0 are also skipped)
foreach ( $matches[2] as $section ) {
$nt = Title::newFromText( $section );
if ( !$nt || $nt->getNamespace() != 0 || $nt->exists() ) continue;
$redirPage = WikiPage::factory( $nt );
if ( !$redirPage ) continue; // can't happen; check anyway
// initialize some variables that we can reuse:
if ( !isset( $redirPrefix ) ) {
$redirPrefix = MagicWord::get( 'redirect' )->getSynonym( 0 );
$redirPrefix .= '[[' . $title->getPrefixedText() . '#';
}
if ( !isset( $reason ) ) {
$reason = wfMsgForContent( 'editsummary-auto-redir-to-section' );
}
// create the page (if we can; errors are ignored):
$redirText = $redirPrefix . $section . "]]\n";
$flags = EDIT_NEW | EDIT_MINOR | EDIT_DEFER_UPDATES;
$redirPage->doEdit( $redirText, $reason, $flags, false, $user );
}
return true;
}
Note: Much of this code is based on bits and pieces of the pagemove redirect creating code from Title.php and the double redirect fixer code, as well as the documentation for WikiPage::doEdit(). I have not actually tested this code, but I think it has at least a decent chance of working as is. Note that you'll need to create the MediaWiki:editsummary-auto-redir-to-section page on your wiki to set a meaningful edit summary for the redirect edits.
I'm trying to design a simple API for a webservice I've written. The problem I'm facing is as follows: a form will present to a user any number of themes. This number will change per database.
The user may pick any number of the themes presented and later on can also assign a number value to them to describe level of relevance.
What I need to do is to be able to pass to the webserivce a 2 dimensional array [themeid: theme value] for each selected theme.
I'm not sure how to do that using HTTP get or POST.
Will appreciate any help!
Why do you need a 2d array? Why not pass a list of pairings back where you use an object to encapsulate a theme id and relevance rating pairing? Here is an example in json:
[
{
"rating": 5,
"themeId": 1
},
{
"rating": 3,
"themeId": 2
}
]
whaley has it right pretty much. You want to use json.
Here is an interactive php session to show you how to do this php->json
php > $root = array();
php > $node = new stdClass();
php > $node->theme = "theme";
php > $node->value = "value";
php > $root[12] = $node;
Here's a print_r of this object, to show you what it looks like in php.
php > print_r($root);
Array
(
[12] => stdClass Object
(
[theme] => theme
[value] => value
)
)
Here's an example of the json output.
php > echo json_encode($root);
{"12":{"theme":"theme","value":"value"}}
In essense, you could push this either POST or GET into your application, and json_decode() it to the object in the first section.