B4J Question [solved]webapp. Is map/list in ThreadSafeMap thread safe?

billzhan

Active Member
Licensed User
Longtime User
Hi,

Is map/list in ThreadSafeMap thread safe? I have to store info in map/list for each thread, code:

B4X:
'In main thread
Public tidInfoMap As Map
Public tidInfoList As Map
...
tidInfoMap=srvr.CreateThreadSafeMap '{threadid:{"tick":"...";"id":"..."}}
tidInfoList=srvr.CreateThreadSafeMap '{threadid:["1","2","3",...]}


'In the threads
    threadid=Main.srvr.CurrentThreadIndex

'map
    Dim m3 As Map =main.tidInfoMap.Get(threadid)
'update map
    If m3.IsInitialized=False Then m3.Initialize
    m3.Put("tick",datetime.now)
    m3.Put("id",id)
'get data
    dim dateticks as long=    m3.get("tick")

  
'list  
    Dim listinfo As List =main.tidInfoList.Get(threadid)
'update list
    listinfo.Add(DateTime.Now)
'get data in list
    listinfo.get(0)
 
Last edited:

billzhan

Active Member
Licensed User
Longtime User
Thanks. Map m3 should be put to main map.

So I think maps created with Server.CreateThreadSafeMap, then put them in the main thread safe map, all these maps will be thread safe. Is this right?

How to iterate all keys of a Thread SafeMap?
According to document, getkeyat is not available. For each in tsMap.Keys :

B4X:
    For Each keystr As String In tsMap.Keys
        log(keystr)
    Next

Error thrown:
B4X:
Error occurred on line: 2990 (db).
java.lang.RuntimeException: Concurrent Map does not support this method.
    at anywheresoftware.b4j.object.ServerWrapper$ConcurrentMyMap.getKey(ServerWrapper.java:312)
    at anywheresoftware.b4a.objects.collections.Map.GetKeyAt(Map.java:95)
    at anywheresoftware.b4a.objects.collections.Map$IterableMap.Get(Map.java:160)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at anywheresoftware.b4a.shell.Shell.runMethod(Shell.java:563)
    at anywheresoftware.b4a.shell.Shell.raiseEventImpl(Shell.java:221)
    at anywheresoftware.b4a.shell.Shell.raiseEvent(Shell.java:156)
    at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at anywheresoftware.b4a.BA.raiseEvent2(BA.java:93)
    at anywheresoftware.b4a.ShellBA.raiseEvent2(ShellBA.java:82)
    at anywheresoftware.b4a.BA.raiseEvent(BA.java:84)
    at anywheresoftware.b4j.object.WebSocketModule$Adapter$ThreadHandler.run(WebSocketModule.java:192)
    at anywheresoftware.b4a.keywords.SimpleMessageLoop.runMessageLoop(SimpleMessageLoop.java:30)
    at anywheresoftware.b4a.StandardBA.startMessageLoop(StandardBA.java:26)
    at anywheresoftware.b4a.ShellBA.startMessageLoop(ShellBA.java:103)
    at anywheresoftware.b4a.keywords.Common.StartMessageLoop(Common.java:131)
    at anywheresoftware.b4a.shell.Shell.raiseEventImpl(Shell.java:292)
    at anywheresoftware.b4a.shell.Shell.raiseEvent(Shell.java:156)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at anywheresoftware.b4a.BA.raiseEvent2(BA.java:93)
...
 
Upvote 0

billzhan

Active Member
Licensed User
Longtime User
B4X:
Dim m As Map = Main.srvr.CreateThreadSafeMap

This is the line missing in my code. Nested Thread Safe Map should be assigned to a map( which is created by CreateThreadSafeMap) ,else error thrown.

Thanks
 
Upvote 0

mindful

Active Member
Licensed User
There is a workaround for the nested maps:
B4X:
Dim m As Map = Main.srvr.CreateThreadSafeMap
   m =main.tidInfoMap.Get(threadid)
   For Each k As String In m.Values
     Log(k)
   Next
Hello, this is only required if we need to use For Each on the nested map ? Or is it a general rule ?

Like if we want to access the nested map could we just do :
B4X:
dim m as Map = main.tidInfoMap.Get(threadid)
m.Put("something", "someone")
....
it seems to work for put and remove methods, instead for each only works if we cast the map as Erel suggested.
 
Upvote 0
Top