Open Source β€’ Background Tasks: Itoo πŸš€

Yes. Exactly!

This could be as simple (though potentially inefficient) as a semaphore - where each thread requests the "lock" asynchronously until it is acquired and release it when done.

Or it could be more sophisticated and, for example, queue access requests and grant them in order of request, granting each subsequent request when access is released.

If none exists in appinventor, then this could be a very useful extension.

I am a little surprised that I find little/no mention of this in the forum (maybe I missed it). It makes me wonder if, for some reason, such a lock was not needed or would not be useful or practical or maybe even not possible.

-Randal

1 Like

You didnt miss it, in App Inventor, there wasant such a complexity to deal with before. App Inventor apps' blocks are single threaded, everything runs on a single thread.

Meaning internally the components may utilize multi threading capabilities, but with a block coder's perspective, there really isnt a way to multi thread on App Inventor.

Race conditions often occur when two different processes/threads try to read and change the same data on the same location. (This issue never arose in App Inventor).

(I am using the word "thread' and "process" inter-changeably here)

Hi
Did some experiments using Ullis Roboter AI2 App Launcher Extension
The extension has a block to check for permission: CanLaunchFromBackground

It seems to work.
It will run the app packages on restart/boot

Here is my blocks
(app packagename blanked out here in this image)

1 Like

That's great if it works.

"Thinking out-loud" ...

It would seem that the basic test-and-set (semaphore) lock functionality could implemented using the:
int getAndSet(int newValue)
method from the AtomicInteger class

[(https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/atomic/AtomicInteger.html)

... which atomically sets to the given value and returns the old value.

public AtomicInteger()
Creates a new AtomicInteger with initial value 0.

see: (https://stackoverflow.com/questions/57832471/which-atomicinteger-methods-are-test-and-set-fetch-and-add-and-compare-and-swap)

Each process/thread wanting access calls getAndSet (1) until it returns a '0'...every subsequent call from a process/thread will be returned a '1'.

Then after performing the protected operation(s), the '1' is reset to a '0' by the process with access by calling getAndSet(0), making it (the '0') available to other process(es)/thread(s).

The '0' is the permission token. It only exists in one place - either in the integer object (as when it is first created) or in a process which obtained it by getAndSet(1), replacing the '0' with a '1' in the object.

In cases where a collision is unlikely and/or the processing to be protected is of short duration (I believe this is true in my use case), the getAndSet(1) maybe done repeatedly ("spin on the lock") since access would likely be granted quickly.

The extension could simply be an "AccessToken" with GetAccess and ReleaseAccess methods which would do the underlying getAndSet calls. Or it could possibly be incorporated into the itoo extension(?).

One problem I see is that a thread/process could not be allowed to die/crash/exit while in possession of the '0', thereby causing any other process/thread calling getAndSet(1) to "hang"... perhaps some sort of timeout could be implemented...

... just "thinking out loud"... "for what it's worth" (excuse the English idioms :frowning: )

-Kind regards,
Randal

Hi, we cannot use any atomic object classes provided by Java, even though they are meant to solve the problem we see, it does not suit us.

This is because, in Android, a normal process cannot access any of the objects stored in service process and vice versa.

AtomicInteger or any atomic type must be stored in either of the process, but it cannot be accessed by another.

Also, this feature could be out of scope for Itoo, since it only deals with background/foreground operations.

We could try to add that feature to this extension, but it wouldnt really suit it's purpose well.

Ok. I can see that what I had in mind using AtomicInteger is not possible in the normal sense of its use...

Let me return to a request in my earlier post:

I want to understand the itoo broadcast mechanism. I'd like to send messages both ways: from foreground UI to the itoo registered service and from the service to the UI, both in the same app.

Can you point me to example code that might help me understand how this broadcast messaging works?

Thanks,
-Randal

Hi, one of the examples showcasing Broadcasting abilities is my music player guide:

Although please note that the version used in the above project is older than the present version. Though the working is almost same.


Or let me try to explain how you'll implement it.

Case1: Send a message from UI to background?

For that, you use the RegisterBroadcast block in the the background, along with arguments "name" and a "procedure". What happens when that particular broadcast "name" is triggered? It will call that "procedure" with one argument, i.e the message.

Then you'll use the Broadcast block, in the UI, along with the name and the message.


Case2: Send a message from background to UI

In the background, similarly, directly, use the Broadcast block, along with the name and the message.
In the UI, there is an event block called BroadcastEvent that triggers whenever a new message is received.

:tada: Itoo's 2nd Anniversary

WOW!!! Its been 2 years from the first launch of Itoo!!!

Itoo is a widely used, special, yet unique tool, that has been redistributed in various forms, hundreds of times!

I would like to heavily thank all of the project supporters, without their encouragement, this extension wouldn't have evolved this further!!

Really thanks to the donors and contributors as well!! This is an extra push, that keeps me motivated!!

And how can we forget the ones that take time to reply to Itoo related queries, lifting some of my weight of? Kudos to them as well!

This in turn, also encourages me to help others, especially students and learners, who can further push the imagination with my tools!!

7 Likes

Thanks, very much for your example and explanation (I might suggest that you add the explanation the next time you update the documentation :slight_smile:

Can both cases be used in the same app so that messages may go in both directions (to/from service)? Or is it one direction only: Case1 OR Case2 in a single app?

If bi-directional is possible, then must the message "names" be distinct/different or could they be the same?

-Randal

1 Like

There shouldnt be a problem using the same message name for bi-directional communication.

If you send a message named X to Service, then the Service can also send back you a messaged named X, there shouldn't be any conflict.

I think I may have solved my problem - needing to protect itoo property data from "simultaneous" access by different threads/processes. (If not, then at least I think I may have found a use for the GetAndSet() function which WOULD provide protection)

Here is the proposed solution where user interface processing and service processing must be protected from simultaneous access:

  1. Each processing is placed in its own procedure (UiProcessing and ServiceProcessing).

  2. When the UI processing is to be done, an itoo.Broadcast (named, say, "UiMsg") is sent.

  3. The Service registers the UiProcessing procedure to execute on message receipt (RegisterBroadcast) of UiMsg. Any arguments needed for this procedure could be contained in the message itself.

  4. When protected processing from the service is to be done, it simply calls ServiceProcessing.

This way the Ui and Service processing procedures execute in the same thread (the service), and no further lock/protection is required. If they somehow execute in different threads (here I confess my ignorance of just how this works), then the GetAndSet() function could provide the required protection.

I have modified my earlier test case to work in this manner, showing where the get and release access calls would go - if needed. What do you think?

itoo_protected_code.aia (880.4 KB)

2 Likes

I think it works good!

Thanks for taking a look at it.

You will note that, while the incrementing of the counts is protected, the reading of them for display by the UI is NOT... I am working on a change so that the read of the counts is also done in the service (on receipt of a message from the UI) and then the service sends these counts to the UI for display using Broadcast to the UI BroadcastEvent.

If you display enough times you will likely note invalid display results. For example, I have seen "-7" for service count which is the "if not there" entry for FetchProperty of the service count.

-Randal

1 Like

I am posting the update which does a safe display of the counts.

Because the counts are now read by the service, the service must be running (tap Start) before any counts will be displayed (Restart app after starting service to display counts.).

Thanks for your help!

Kind regards,
Randal


itoo_protected_code.aia (880.6 KB)

1 Like

I am using the itoo persistent property feature (StoreProperty, FetchProperty) and find that I want to display (at least for debug purposes) the value of each named property which has been stored. As I search through my blocks for ".StoreProperty" so as to build a list of them through which to iterate and log/display, the thought occurred to me that if there were an itoo.GetPropertyList block, it would be very useful :slight_smile:

Just a thought for a future enhancement.

Kind regards,
Randal

2 Likes

You can store/fetch whatever you want, this can also be a list or a dictionary

Taifun

Ok...so are you suggesting that, for example, I write a StoreProperty wrapper procedure which first Fetches an item named "propertyList" (using itoo.FecthProperty) adds the item name (being stored) to the list (if not already on in the list) and then StoreProperty the named item as well as the possibly modified list?

And then when I want a list of properties that have been stored, I simply FetchProperty (propertyList)?

???,
Randal

Yes, for example
Taifun

Thanks for the suggestion!

Here is what I came up with - perhaps too many output options (log, screen, label ... at least I stopped short of a "toFile" option :slight_smile: )

It seems to do the trick.

Comments? Suggestions? Corrections?

The only thing I don't like about it is that I would like to check "theLabel" argument to be sure it is a label. But I could not figure out how... :frowning:

-Randal

StoreItooProperty:

DumpItooProperties:

Kind regards,
Randal

2 Likes