Dynamic thread names

classic Classic list List threaded Threaded
9 messages Options
Reply | Threaded
Open this post in threaded view
|

Dynamic thread names

Da'oud Rashid
Hi all,

I’m in the process of upgrading from Lasso 8.5 to 9.x.

I’m looking to replace my global vars with define threadName => somevalue .

However, there are a number of instances in my old code where the global variable names are dynamic:

Global($aVariableName + ’Something’ = $aVariable)

Is it possible to do something similar for thread names? For example, something like the following (which doesn’t work):

define ($myThreadName) => $aVariable->ascopydeep

and

$aVariable = thread($myThreadName)->ascopydeep

I can do the following:

define myMap => thread{
        parent map

        public oncreate => ..oncreate

        public load(map::map) => {
                #map->foreachpair => {
                        self->insert(#1->first->ascopydeep = #1->second->ascopydeep)
                }
        }
}

myMaps->load($mapOfVars)

However, I’d prefer to create separate threads….mainly so I don’t run into issues with a heavy volume of concurrent access to the threads. Also, iterating through each item in the map doesn’t seem like a very efficient way to decouple the thread from the thread variable.

As an aside, I’m curious to know why ascopydeep doesn’t seem to work for threads (and doesn’t throw an error):

local(
        item1Ref = 'item1',
        foo = 'unchanged'
)
       
var(
        myMap = map(#item1Ref = #foo),
        mySecondMap = $myMap->ascopydeep
)

define myThread => $myMap->ascopydeep
       
$myMap->find(#item1Ref) = ‘changed'

$mySecondMap->find(#item1Ref)
// result: unchanged (as expected)

myThread->Find(#item1Ref)
// result: changed (unexpected)

—— AND — —

define myMap => thread{
        parent map

        public oncreate => ..oncreate
}

myMap->Insert(‘item1’ = ‘unchanged’)

var(mySecondMap = myThread->ascopydeep)

$mySecondMap->Find(’item1’) = ‘changed’

$mySecondMap->Find(‘item1’)
// result: changed (expected)

myThread->Find(‘item1’)
// result: changed (unexpected)

Unfortunately, myMap->foreachpair => {…} doesn’t seem to work (it throws an error), so I can’t use that to copy values into a thread variable.

Thank you,
Da’oud

#############################################################

This message is sent to you because you are subscribed to
  the mailing list Lasso [hidden email]
Official list archives available at http://www.lassotalk.com
To unsubscribe, E-mail to: <[hidden email]>
Send administrative queries to  <[hidden email]>
Reply | Threaded
Open this post in threaded view
|

Re: Dynamic thread names

Ke Carlton-3
I think it's important to highlight that while there's some similarities
between globals and thread objects that they are actually very different
beasts.

You will need to adjust your approach to fit within how thread objects
work.

It's a very bad idea to copy all the values from a thread object to local
variables; as when you do so it locks the thread while the data is copied
(it's always copied, never referenced).

It's far better to retrieve snippets of data as you need them as this
blocks the thread for less time. Obviously this varies from situation to
situation and the amount of data involved.

If you're using them to load settings for various sites, consider making a
parent type that will load the settings for that thread and have all your
threads inherit from that. For example:

define somethread => thread {
parent settingsloader

public oncreate => {
.load('somekey')
}
}

define anotherthread => thread {
parent settingsloader

public oncreate => {
.load('anotherkey')
}
}

In terms of addressing the threads dynamically you can do so with the
standard backslash invoke syntax:

local(
threadname = 'anotherthread',
thread = (\#threadname)()
)

You can also create helpers for this:

define get_thread(thread::tag) => (\#thread)()
define get_thread(thread::string) => (\#thread)()

Finally you could always dynamically create the threads; however I would
not recommend this approach as if you're starting to consider such routes
you're probably doing some important things fundamentally wrong:

define create_thread(thread::tag) => {
! #thread->istype
? sourcefile(`
       define ` + #thread->asstring + ` => thread {
           parent map
           public oncreate => ..oncreate
       }
   `, #thread->asstring, false, false)()

   return (\#thread)()
}


local(thread) = create_thread(::mythread) // returns a newly created or
existing mythread map thread

To summarise some of the major differences between globals and threads:

   - Threads lock during both reads and writes (keep processing time low)
   - Threads always copy data when returning data
   - Threads are a defined type, whereas globals are an assigned value
   - Once defined threads will always exist

Ke




On Thu, Mar 31, 2016 at 5:02 AM Da'oud Rashid <[hidden email]> wrote:

> Hi all,
>
> I’m in the process of upgrading from Lasso 8.5 to 9.x.
>
> I’m looking to replace my global vars with define threadName => somevalue .
>
> However, there are a number of instances in my old code where the global
> variable names are dynamic:
>
> Global($aVariableName + ’Something’ = $aVariable)
>
> Is it possible to do something similar for thread names? For example,
> something like the following (which doesn’t work):
>
> define ($myThreadName) => $aVariable->ascopydeep
>
> and
>
> $aVariable = thread($myThreadName)->ascopydeep
>
> I can do the following:
>
> define myMap => thread{
>         parent map
>
>         public oncreate => ..oncreate
>
>         public load(map::map) => {
>                 #map->foreachpair => {
>                         self->insert(#1->first->ascopydeep =
> #1->second->ascopydeep)
>                 }
>         }
> }
>
> myMaps->load($mapOfVars)
>
> However, I’d prefer to create separate threads….mainly so I don’t run into
> issues with a heavy volume of concurrent access to the threads. Also,
> iterating through each item in the map doesn’t seem like a very efficient
> way to decouple the thread from the thread variable.
>
> As an aside, I’m curious to know why ascopydeep doesn’t seem to work for
> threads (and doesn’t throw an error):
>
> local(
>         item1Ref = 'item1',
>         foo = 'unchanged'
> )
>
> var(
>         myMap = map(#item1Ref = #foo),
>         mySecondMap = $myMap->ascopydeep
> )
>
> define myThread => $myMap->ascopydeep
>
> $myMap->find(#item1Ref) = ‘changed'
>
> $mySecondMap->find(#item1Ref)
> // result: unchanged (as expected)
>
> myThread->Find(#item1Ref)
> // result: changed (unexpected)
>
> —— AND — —
>
> define myMap => thread{
>         parent map
>
>         public oncreate => ..oncreate
> }
>
> myMap->Insert(‘item1’ = ‘unchanged’)
>
> var(mySecondMap = myThread->ascopydeep)
>
> $mySecondMap->Find(’item1’) = ‘changed’
>
> $mySecondMap->Find(‘item1’)
> // result: changed (expected)
>
> myThread->Find(‘item1’)
> // result: changed (unexpected)
>
> Unfortunately, myMap->foreachpair => {…} doesn’t seem to work (it throws
> an error), so I can’t use that to copy values into a thread variable.
>
> Thank you,
> Da’oud
>
> #############################################################
>
> This message is sent to you because you are subscribed to
>   the mailing list Lasso [hidden email]
> Official list archives available at http://www.lassotalk.com
> To unsubscribe, E-mail to: <[hidden email]>
> Send administrative queries to  <[hidden email]>

#############################################################

This message is sent to you because you are subscribed to
  the mailing list Lasso [hidden email]
Official list archives available at http://www.lassotalk.com
To unsubscribe, E-mail to: <[hidden email]>
Send administrative queries to  <[hidden email]>
Reply | Threaded
Open this post in threaded view
|

Re: Dynamic thread names

Da'oud Rashid
Hi Ke,

Many thanks for the detailed response. It is greatly appreciated. Yes, threads are very different beasts indeed!

The backslash invoke syntax and the method to create dynamically-named threads were exactly what I was looking for (but couldn’t find in the documentation).

I have multiple localized domains running off-of one “site” in Lasso 8.5. We list about 3,500 products in multiple languages and currencies.

In Lasso 8.5, the global variables are loaded at startup and help me avoid excessive database queries when pre-rendering individual product pages and galleries. As such, the majority of global vars aren’t read or written to when a web page is loaded by site visitors.

As for the dynamically-named global vars, these are used to store a pre-ordered array of productIds to be displayed in specific galleries (for example, a gallery showing items of a particular category…where I don’t know the category names in advance). For various reasons, I prefer to use dynamically-named global variables for these, rather than put them all in one large map.

I am concerned, however, with a large global variable I use to store a map of language localizations (parts of which are accessed during page loads). I'll be looking alternative ways to store/access this before we go live. I read the LassoSoft article about your success with www.cancomuk.com and will be looking at memcached and some other alternatives (and also looking at replacing my inlines with Datasource, which looks great!).

With your help and a bit of experimentation with methods within define aThread => thread{parent map…}, I’ve managed to copy data in and out of threads (which, in my case, occasionally need their data updated). Where I run into thread-locking issues before going live, I’ll look at alternative approaches.

Thanks again!

Kind regards,
Da’oud

> On Mar 31, 2016, at 1:54 AM, Ke Carlton <[hidden email]> wrote:
>
> I think it's important to highlight that while there's some similarities
> between globals and thread objects that they are actually very different
> beasts.
>
> You will need to adjust your approach to fit within how thread objects
> work.
>
> It's a very bad idea to copy all the values from a thread object to local
> variables; as when you do so it locks the thread while the data is copied
> (it's always copied, never referenced).
>
> It's far better to retrieve snippets of data as you need them as this
> blocks the thread for less time. Obviously this varies from situation to
> situation and the amount of data involved.
>
> If you're using them to load settings for various sites, consider making a
> parent type that will load the settings for that thread and have all your
> threads inherit from that. For example:
>
> define somethread => thread {
> parent settingsloader
>
> public oncreate => {
> .load('somekey')
> }
> }
>
> define anotherthread => thread {
> parent settingsloader
>
> public oncreate => {
> .load('anotherkey')
> }
> }
>
> In terms of addressing the threads dynamically you can do so with the
> standard backslash invoke syntax:
>
> local(
> threadname = 'anotherthread',
> thread = (\#threadname)()
> )
>
> You can also create helpers for this:
>
> define get_thread(thread::tag) => (\#thread)()
> define get_thread(thread::string) => (\#thread)()
>
> Finally you could always dynamically create the threads; however I would
> not recommend this approach as if you're starting to consider such routes
> you're probably doing some important things fundamentally wrong:
>
> define create_thread(thread::tag) => {
> ! #thread->istype
> ? sourcefile(`
>       define ` + #thread->asstring + ` => thread {
>           parent map
>           public oncreate => ..oncreate
>       }
>   `, #thread->asstring, false, false)()
>
>   return (\#thread)()
> }
>
>
> local(thread) = create_thread(::mythread) // returns a newly created or
> existing mythread map thread
>
> To summarise some of the major differences between globals and threads:
>
>   - Threads lock during both reads and writes (keep processing time low)
>   - Threads always copy data when returning data
>   - Threads are a defined type, whereas globals are an assigned value
>   - Once defined threads will always exist
>
> Ke
>
>
>
>
> On Thu, Mar 31, 2016 at 5:02 AM Da'oud Rashid <[hidden email]> wrote:
>
>> Hi all,
>>
>> I’m in the process of upgrading from Lasso 8.5 to 9.x.
>>
>> I’m looking to replace my global vars with define threadName => somevalue .
>>
>> However, there are a number of instances in my old code where the global
>> variable names are dynamic:
>>
>> Global($aVariableName + ’Something’ = $aVariable)
>>
>> Is it possible to do something similar for thread names? For example,
>> something like the following (which doesn’t work):
>>
>> define ($myThreadName) => $aVariable->ascopydeep
>>
>> and
>>
>> $aVariable = thread($myThreadName)->ascopydeep
>>
>> I can do the following:
>>
>> define myMap => thread{
>>        parent map
>>
>>        public oncreate => ..oncreate
>>
>>        public load(map::map) => {
>>                #map->foreachpair => {
>>                        self->insert(#1->first->ascopydeep =
>> #1->second->ascopydeep)
>>                }
>>        }
>> }
>>
>> myMaps->load($mapOfVars)
>>
>> However, I’d prefer to create separate threads….mainly so I don’t run into
>> issues with a heavy volume of concurrent access to the threads. Also,
>> iterating through each item in the map doesn’t seem like a very efficient
>> way to decouple the thread from the thread variable.
>>
>> As an aside, I’m curious to know why ascopydeep doesn’t seem to work for
>> threads (and doesn’t throw an error):
>>
>> local(
>>        item1Ref = 'item1',
>>        foo = 'unchanged'
>> )
>>
>> var(
>>        myMap = map(#item1Ref = #foo),
>>        mySecondMap = $myMap->ascopydeep
>> )
>>
>> define myThread => $myMap->ascopydeep
>>
>> $myMap->find(#item1Ref) = ‘changed'
>>
>> $mySecondMap->find(#item1Ref)
>> // result: unchanged (as expected)
>>
>> myThread->Find(#item1Ref)
>> // result: changed (unexpected)
>>
>> —— AND — —
>>
>> define myMap => thread{
>>        parent map
>>
>>        public oncreate => ..oncreate
>> }
>>
>> myMap->Insert(‘item1’ = ‘unchanged’)
>>
>> var(mySecondMap = myThread->ascopydeep)
>>
>> $mySecondMap->Find(’item1’) = ‘changed’
>>
>> $mySecondMap->Find(‘item1’)
>> // result: changed (expected)
>>
>> myThread->Find(‘item1’)
>> // result: changed (unexpected)
>>
>> Unfortunately, myMap->foreachpair => {…} doesn’t seem to work (it throws
>> an error), so I can’t use that to copy values into a thread variable.
>>
>> Thank you,
>> Da’oud
>>
>> #############################################################
>>
>> This message is sent to you because you are subscribed to
>>  the mailing list Lasso [hidden email]
>> Official list archives available at http://www.lassotalk.com
>> To unsubscribe, E-mail to: <[hidden email]>
>> Send administrative queries to  <[hidden email]>
>
> #############################################################
>
> This message is sent to you because you are subscribed to
>  the mailing list Lasso [hidden email]
> Official list archives available at http://www.lassotalk.com
> To unsubscribe, E-mail to: <[hidden email]>
> Send administrative queries to  <[hidden email]>


#############################################################

This message is sent to you because you are subscribed to
  the mailing list Lasso [hidden email]
Official list archives available at http://www.lassotalk.com
To unsubscribe, E-mail to: <[hidden email]>
Send administrative queries to  <[hidden email]>
Reply | Threaded
Open this post in threaded view
|

Re: Dynamic thread names

Ke Carlton-3
The back slash is documented here:
http://lassoguide.com/language/operators.html?highlight=invoke#method-escaping

the documentation is pretty solid now.

I would take a look at Redis, it's far surpassed memcached in terms of
features and performance. If your in the process of a rewrite it's a pretty
good time to wrap your head around it: www.redis.io

There's a Lasso connector for it here:
https://github.com/Zeroloop/lasso-redis

It may also be worth pointing out that there are alternatives to thread
objects. For example you can have lasso generate code. ie. a large case
statement like the below:

define site_y_setting(name::string) => {
switch(#name) => {
case('something') return 2.3
case('another') return 'some string'
}
}

Or even a cached map:

define site_x_settings => cache_method => {
return map(
'something' = 2.4,
'another' = 'a really long string'
)
}
        // https://gist.github.com/Ke-/5a631f50eb5366b9cc35

This type of approach is particularly useful if things do not change often.

Another approach to deal with thread locking is just to run more than one
Lasso instance. This makes sense on a lot on levels — particularly as
redundancy should no longer be considered as an "optional" in a modern
setup.

However you will need to find the best approach that suites your needs /
situation.

Good luck!

Ke

On Thu, 31 Mar 2016 at 22:55 Da'oud Rashid <[hidden email]> wrote:

> Hi Ke,
>
> Many thanks for the detailed response. It is greatly appreciated. Yes,
> threads are very different beasts indeed!
>
> The backslash invoke syntax and the method to create dynamically-named
> threads were exactly what I was looking for (but couldn’t find in the
> documentation).
>
> In Lasso 8.5, the global variables are loaded at startup and help me avoid
> excessive database queries when pre-rendering individual product pages and
> galleries. As such, the majority of global vars aren’t read or written to
> when a web page is loaded by site visitors.
>
>

#############################################################

This message is sent to you because you are subscribed to
  the mailing list Lasso [hidden email]
Official list archives available at http://www.lassotalk.com
To unsubscribe, E-mail to: <[hidden email]>
Send administrative queries to  <[hidden email]>
Reply | Threaded
Open this post in threaded view
|

Re: Dynamic thread names

Da'oud Rashid
Great tips. Thanks very much, Ke!

> On Mar 31, 2016, at 3:35 PM, Ke Carlton <[hidden email]> wrote:
>
> The back slash is documented here:
> http://lassoguide.com/language/operators.html?highlight=invoke#method-escaping
> —
> the documentation is pretty solid now.
>
> I would take a look at Redis, it's far surpassed memcached in terms of
> features and performance. If your in the process of a rewrite it's a pretty
> good time to wrap your head around it: www.redis.io
>
> There's a Lasso connector for it here:
> https://github.com/Zeroloop/lasso-redis
>
> It may also be worth pointing out that there are alternatives to thread
> objects. For example you can have lasso generate code. ie. a large case
> statement like the below:
>
> define site_y_setting(name::string) => {
> switch(#name) => {
> case('something') return 2.3
> case('another') return 'some string'
> }
> }
>
> Or even a cached map:
>
> define site_x_settings => cache_method => {
> return map(
> 'something' = 2.4,
> 'another' = 'a really long string'
> )
> }
>        // https://gist.github.com/Ke-/5a631f50eb5366b9cc35
>
> This type of approach is particularly useful if things do not change often.
>
> Another approach to deal with thread locking is just to run more than one
> Lasso instance. This makes sense on a lot on levels — particularly as
> redundancy should no longer be considered as an "optional" in a modern
> setup.
>
> However you will need to find the best approach that suites your needs /
> situation.
>
> Good luck!
>
> Ke
>
> On Thu, 31 Mar 2016 at 22:55 Da'oud Rashid <[hidden email]> wrote:
>
>> Hi Ke,
>>
>> Many thanks for the detailed response. It is greatly appreciated. Yes,
>> threads are very different beasts indeed!
>>
>> The backslash invoke syntax and the method to create dynamically-named
>> threads were exactly what I was looking for (but couldn’t find in the
>> documentation).
>>
>> In Lasso 8.5, the global variables are loaded at startup and help me avoid
>> excessive database queries when pre-rendering individual product pages and
>> galleries. As such, the majority of global vars aren’t read or written to
>> when a web page is loaded by site visitors.
>>
>>
>
> #############################################################
>
> This message is sent to you because you are subscribed to
>  the mailing list Lasso [hidden email]
> Official list archives available at http://www.lassotalk.com
> To unsubscribe, E-mail to: <[hidden email]>
> Send administrative queries to  <[hidden email]>


#############################################################

This message is sent to you because you are subscribed to
  the mailing list Lasso [hidden email]
Official list archives available at http://www.lassotalk.com
To unsubscribe, E-mail to: <[hidden email]>
Send administrative queries to  <[hidden email]>
Reply | Threaded
Open this post in threaded view
|

Re: Dynamic thread names

Jolle Carlestam-2
In reply to this post by Ke Carlton-3
31 mars 2016 kl. 12:35 skrev Ke Carlton <[hidden email]>:
>
> define site_y_setting(name::string) => {
> switch(#name) => {
> case('something') return 2.3
> case('another') return 'some string'
> }
> }

I’m fairly certain that ”switch" is something you do on the days you’ve switched to another programming language. Any day you prefer coding in Lasso you would call it ”match”.

HDB
Jolle

#############################################################

This message is sent to you because you are subscribed to
  the mailing list Lasso [hidden email]
Official list archives available at http://www.lassotalk.com
To unsubscribe, E-mail to: <[hidden email]>
Send administrative queries to  <[hidden email]>
Reply | Threaded
Open this post in threaded view
|

Re: Dynamic thread names

Ke Carlton-3
Yeah; shows how much time I spend in JS land now. Think it used to be
switch in L8 — what matters is the gist is there.


On Fri, Apr 1, 2016 at 5:27 PM Jolle Carlestam <[hidden email]> wrote:

> 31 mars 2016 kl. 12:35 skrev Ke Carlton <[hidden email]>:
> >
> > define site_y_setting(name::string) => {
> > switch(#name) => {
> > case('something') return 2.3
> > case('another') return 'some string'
> > }
> > }
>
> I’m fairly certain that ”switch" is something you do on the days you’ve
> switched to another programming language. Any day you prefer coding in
> Lasso you would call it ”match”.
>
> HDB
> Jolle
>
> #############################################################
>
> This message is sent to you because you are subscribed to
>   the mailing list Lasso [hidden email]
> Official list archives available at http://www.lassotalk.com
> To unsubscribe, E-mail to: <[hidden email]>
> Send administrative queries to  <[hidden email]>

#############################################################

This message is sent to you because you are subscribed to
  the mailing list Lasso [hidden email]
Official list archives available at http://www.lassotalk.com
To unsubscribe, E-mail to: <[hidden email]>
Send administrative queries to  <[hidden email]>
Reply | Threaded
Open this post in threaded view
|

Re: Dynamic thread names

Jolle Carlestam-2
1 apr. 2016 kl. 06:32 skrev Ke Carlton <[hidden email]>:
>
> Think it used to be
> switch in L8

If memory serves me it was ”select”.

HDB
Jolle

#############################################################

This message is sent to you because you are subscribed to
  the mailing list Lasso [hidden email]
Official list archives available at http://www.lassotalk.com
To unsubscribe, E-mail to: <[hidden email]>
Send administrative queries to  <[hidden email]>
Reply | Threaded
Open this post in threaded view
|

Re: Dynamic thread names

Ke Carlton-3
Triply highlights how much time I spend in JS land.

On Fri, Apr 1, 2016 at 5:35 PM Jolle Carlestam <[hidden email]> wrote:

> 1 apr. 2016 kl. 06:32 skrev Ke Carlton <[hidden email]>:
> >
> > Think it used to be
> > switch in L8
>
> If memory serves me it was ”select”.
>
> HDB
> Jolle
>
> #############################################################
>
> This message is sent to you because you are subscribed to
>   the mailing list Lasso [hidden email]
> Official list archives available at http://www.lassotalk.com
> To unsubscribe, E-mail to: <[hidden email]>
> Send administrative queries to  <[hidden email]>

#############################################################

This message is sent to you because you are subscribed to
  the mailing list Lasso [hidden email]
Official list archives available at http://www.lassotalk.com
To unsubscribe, E-mail to: <[hidden email]>
Send administrative queries to  <[hidden email]>