Roku Developer Program

Join our online forum to talk to Roku developers and fellow channel creators. Ask questions, share tips with the community, and find helpful resources.
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
sanyam
Visitor

Re: Information on multi-threading

I am requesting(http) multiple images for my carousel and using the request id to map and store the image received to an appropriate location in an roAssociative array.
For this, I use the request id generated by the roTextureRequest object (as mentioned in the sdk doc, this id is unique).
But I see cases when this ID is not unique and the image that was requested later with same request id overwrites the older one.

does anybody else faced this issue?
Am I going wrong somewhere or is this a firmware bug?
0 Kudos
NewManLiving
Visitor

Re: Information on multi-threading

First of all you need to test to insure that you have a valid bitmap returned.
getbitmap is not always valid even though there is a unique id generated
And the URL is what you have requested. If you are putting your requests in an associative array
and your key is not Found upon return then the bitmap returned is probably invalid as well

Next I found it best not to reuse requests. But make a new one each time you request
The same image. This returns immediately if the bitmap is already in cache
You can also save the returned bitmap. If you save the bitmap
you have to make sure that you dereference it when no longer needed
So that memory is released. But saving the requests and
Reusing them was problematic for me
My Channels: 2D API Framework Presentation: https://owner.roku.com/add/2M9LCVC
Updated: 11-11-2015 - Completed Keyboard interface
The Joel Channel ( Final Beta )
0 Kudos
sanyam
Visitor

Re: Information on multi-threading

I am saving the bitmap and yes I am creating a new request everytime.
I am also checking wether the bitmap returned is valid or not. If it is not valid, I am creating a new request.
All this is already in place. I just skipped this info for brevity.
But still I get duplicate request id's often. And the request id's are not the ones of the last request, but they are duplicating randomly.
I just maintained an array to keep all the req id's i have used and checking if the current request id has already occurred.
Also I saw that if i create a request object and face that the request id was duplicated for some previous request, and I create a new request object, it gives me the same duplicate id. I do not get a new id until i send the request for that duplicate id.
Any idea, if something is fishy in my code or in firmware?
0 Kudos
sanyam
Visitor

Re: Information on multi-threading

I cannot put the exact code here, but believe me all the info required to debug this problem is provided in this snippet.
Do you have any suggestions in this code, where i would have gone wrong while sending requests.
I am not adding the part of handling requests in this post.

if location <> invalid then
request = CreateObject("roTextureRequest", location)
' Set certs in this line

m.textureManager.RequestTexture(request)

' Get the ID
id = m.getIDStr(request)
while m.usedIds[id] <> invalid
request = CreateObject("roTextureRequest", location)
'Certs stuff here
//If next line is not executed, this loop becomes an infinite loop
m.textureManager.RequestTexture(request)
id = m.getIDStr(request)
print("DUPLICATE ID FOUND HERE " + id)
end while

m.usedIds[id] = 1
print("Request ID: " + id)

' store url here in case it is needed for retry
return id
else
print("location is invalid")
return invalid
end if
0 Kudos
TheEndless
Channel Surfer

Re: Information on multi-threading

I've never run into this case, so something is definitely off. Can you provide the code for your GetIDStr() function?
My Channels: http://roku.permanence.com - Twitter: @TheEndlessDev
Instant Watch Browser (NetflixIWB), Aquarium Screensaver (AQUARIUM), Clever Clocks Screensaver (CLEVERCLOCKS), iTunes Podcasts (ITPC), My Channels (MYCHANNELS)
0 Kudos
NewManLiving
Visitor

Re: Information on multi-threading

Although I am still exploring the texturemanager, I can tell you what I have learned so far. This may change

A: If you are using the asynchronous services of the manager, which most of us do, you need to keep it that way. So
you should perform what is known as hand-shaking. The best way I have found to do this so far is by using an associativearray

Create an associative array above the scope of your texture processing
Create your texturerequest. Once created the Unique ID is avalible so get it before you send the request to the texturemanager
and add it to your list along with the request.

Create a function or just Fire off all your requests and return without polling anything

Function SendAll( urlArray As Object )

m.MyList.Clear()


for each url In urlArray

request = CreateObject( "roTextureRequest", url )

m.myList.AddReplace( request.GetID().ToStr(), request )

myTextureManager.RequestTexture( request )

end for

return
End Function

Once back in your message loop listen on the port you have defined for your TextureManager. It really is best to use a separate port only for your requests
Forget about wait and use getMessage


' Create and set the port
tPort = CreateObject( "roMessagePort")
myTextureManager.SetMessagePort( tPort )

' Send all requests
SendAll()

' Go into message loop
while true

' As they come in then just process each one
tmsg = tPort.GetMessage()
if tmsg <> Invalid

ReceiveTexture( tmsg)

end if

' If you have another interface port then you can process them as well. but they should be brief until all you sent is received. usually just to exit or
'scroll the screen
msg = uPort.Getmessage()
if msg <> Invalid....

end while


Now your receive would look something like this

Function ReceiveTexture( msg As DYNAMIC ) As Void

' Create the string key and get the value from your list
key = msg.GetID().ToStr()
value = m.myList.LookUp( key )

' If the key is not found in your list (and this does happen) and the bitmap is also invalid then what is going on with the
' texture manager we are not told. (Could be that I am doing something I have not discovered yet but don't think so)
' It may have something to do with keeping an active connection alive until all is received
' However, if value is invalid but the bitmap is valid then likely there is something wrong with your code. You should use a dedicated port
' to receive only the requests that you sent, so no other bitmaps should be coming in that cannot be identified
if value = Invalid
if msg.GetBitmap() <> Invalid
try to find your error
end if

return
end if

' Ok now that you have a valid value just delete it from your list. With this method I have never had a duplicate key
m.myList.Delete( key )

' Now process the message
state = a_msg.GetState()

'If return state is 3 then process the bitmap if valid, should always be when you reach this point
if state = 3

bitmap = msg.GetBitmap()

if bitmap <> Invalid

Do something with the bitmap and return. As I mentioned above you can also use an aa to include a service or
parameters to instruct the screen where to draw
request = value.Request
rect = value.Rect
screen.DrawObject( rect.x, rect.y, bitmap)
return
else

may want to attempt to resend it but if you do use some type of counter so if there is something really wrong you only
resend a couple of times. I designed an object called AsyncManager that handles all this for me

end if

else if state = .....
...
end if

return True

End Function


Well that is the general idea. May be some typo mistakes but you should get the idea. In my AsyncManager object, I have counters, error lists so I always
know what is going on. I can also pre-fetch using a type of polling but if you do this you would send x number of requests and then poll. Do not send/poll each one
It seems that the more you send the more responsive it is. I have never seen a duplicate id using this method. But, I would really like to know what is happening when I get these responses with invalid bitmap, state = 3,
my correct url, and an ID that is not in my list. seems to happen when things are a little slower
My Channels: 2D API Framework Presentation: https://owner.roku.com/add/2M9LCVC
Updated: 11-11-2015 - Completed Keyboard interface
The Joel Channel ( Final Beta )
0 Kudos
TheEndless
Channel Surfer

Re: Information on multi-threading

"NewManLiving" wrote:
But, I would really like to know what is happening when I get these responses with invalid bitmap, state = 3,
my correct url, and an ID that is not in my list. seems to happen when things are a little slower

Unless I misread you previously, I believe you said you were issuing literally hundreds of requests. If that's true (I don't think that's a good idea, but that's another discussion), at a guess.. could it be requests that were issued early on, and have since cycled out of the LRU cache? In other words, the texture request was successful, but you've requested enough other images since then, that it's been cleared from the cache to make room for new images.
My Channels: http://roku.permanence.com - Twitter: @TheEndlessDev
Instant Watch Browser (NetflixIWB), Aquarium Screensaver (AQUARIUM), Clever Clocks Screensaver (CLEVERCLOCKS), iTunes Podcasts (ITPC), My Channels (MYCHANNELS)
0 Kudos
NewManLiving
Visitor

Re: Information on multi-threading

Well right now there are a maximum of 60 requests at one time. There are a number of categories. As the user selects a new category for the grid, I cleanup the texturemanager and then asynchronously load all bitmaps for the next category. Anywhere from 30 to 60. They arrive in the grid rapidly and are drawn immediately to the visible cells in the grid and all bitmaps are saved for the duration of that category. So the current senario is: When the user selects a new category, all bitmaps are set to invalid for the previous category , the manager is completely emptied and then the new textures are loaded anywhere from 30 to 60. As they come in the new bitmaps for that category are saved and the visible portion of the grid is updated. If the user scrolls the grid, then the scrolling function also processes returns and the grid is updated as the user is scrolling. I chose not to wait for a key release to update the grid. Response time is excellent, scrolling my grid is smooth and even. Even with the 2x box. Memory left available when everything completes is 20 - 25 mb depending on the number of textures in the category. Most of the time there is nothing returned as invalid. But, from time to time I get an Identifier that I do not find in my list (I send all requests and immediately begin to listen on the port. The port is dedicated and created fresh each time I need textures) So there is really no lag between send and receive and no other bitmaps are sent. The identifier returned is not found in my dictionary but a validation of the dictionary shows everything intact and eventually does come in . I always receive everything I requested, even with the invalids thrown in. But like I said, there is a unique Identifier, one that I did not request or save, The bitmap is always invalid, the state code is always 3, and the URI is a valid URI that I requested. There is also a slight lag in updating the grid when this happens. So while everything works great I would like to find out if this is to be expected or is there something that I have overlooked
My Channels: 2D API Framework Presentation: https://owner.roku.com/add/2M9LCVC
Updated: 11-11-2015 - Completed Keyboard interface
The Joel Channel ( Final Beta )
0 Kudos
NewManLiving
Visitor

Re: Information on multi-threading

One thing that I did notice is that the example in the docs also tests for a valid bitmap. What's the reason for this if everything else lined up ok. You would think that if everything completed as expected then the bitmap should always be valid. Otherwise I would expect failure to be returned. Apparently it is not or I am missing something
My Channels: 2D API Framework Presentation: https://owner.roku.com/add/2M9LCVC
Updated: 11-11-2015 - Completed Keyboard interface
The Joel Channel ( Final Beta )
0 Kudos