Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Improve the design of stationiterator in oasis #195

Open
CodeBear801 opened this issue Mar 5, 2020 · 1 comment
Open

Improve the design of stationiterator in oasis #195

CodeBear801 opened this issue Mar 5, 2020 · 1 comment
Assignees
Labels
Ideas Ideas for long-term discussion

Comments

@CodeBear801
Copy link

CodeBear801 commented Mar 5, 2020

oasis stationiterator is used to iterate nearby charge station around specific location. Which provide abstraction of charge stations for algorithms to use.

Current situation

The iterator returns a channel which contains charge station elements

iterateNearbyStations() <-chan ChargeStationInfo

In current implementation of iterateNearbyStations(), it use read-write lock to guarantee ChargeStationInfo be properly copied into channel. The users of those iterator could running in its individual go-routine.
Here is related logic:

func (bf *basicFinder) getNearbyChargeStations(req *nearbychargestation.Request) {

To be improved

After the construction of each object which implements the interface of iterateNearbyStations(), it is safe to be used for concurrency algorithm. But if the construction is not finished, users calling iterateNearbyStations() will get an empty channel.

Here is current algorithm:

			go func(index int) {
				iterators[index] = NewLowEnergyLocationStationFinder(sc, locations[index])
				glog.Infof("Finish generating NewLowEnergyLocationStationFinder for %d", index)
                                 // [to be improved] whether iterator is ready or not should hide inside iterator
                                 //  If not ready user of iterator should hang there
				<-isIteratorReady[index-1]
				isIteratorReady[index] <- true
				putWeightBetweenChargeStationsIntoChannel(iterators[index-1], iterators[index], c, oc)
				glog.Infof("Finish generating putWeightBetweenChargeStationsIntoChannel for %d", index)
				wg.Done()
			}(i)

The isIteratorReady is needed here due to: there might be 10 go-routines running go func(index int), each go-routine need previous go-routine finishes

iterators[index] = NewLowEnergyLocationStationFinder(sc, locations[index])

then could execute

putWeightBetweenChargeStationsIntoChannel(iterators[index-1], iterators[index], c, oc)

The ideal situation is, when the construction is not finished, the channel will be empty waiting for input and user side will hang there. And the iterator constructor side will do heavy work(communicate with other services, prepare information) and then put results in all waited channel. And in the future call it will directly send information out.

So upper logic could be changed to

			go func(index int) {
				iterators[index] = NewLowEnergyLocationStationFinder(sc, locations[index])
				glog.Infof("Finish generating NewLowEnergyLocationStationFinder for %d", index)
				putWeightBetweenChargeStationsIntoChannel(iterators[index-1], iterators[index], c, oc)
				glog.Infof("Finish generating putWeightBetweenChargeStationsIntoChannel for %d", index)
				wg.Done()
			}(i)

iterators creation should be very quick and could move to the beginning of all logic, when execute

putWeightBetweenChargeStationsIntoChannel(iterators[index-1], iterators[index], c, oc)

If specific iterator is not ready(still getting data from cloud) should hang there

@CodeBear801 CodeBear801 added the Ideas Ideas for long-term discussion label Mar 5, 2020
@CodeBear801 CodeBear801 self-assigned this Mar 5, 2020
@CodeBear801
Copy link
Author

CodeBear801 commented Mar 6, 2020

I think could use a chan chan is for this situation.
When external user asks for a iterator, it immediately get a channel of channel, when he want to retrieve data from internal channel, if channel is not ready iterator will hang there.

producer part's code

create chan chan and returns it

put this channel in his task queue

iterator part's code

for {
    select {
            // when task queue has request && data is ready
             <- task and put data into channel

    }

}

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
Ideas Ideas for long-term discussion
Projects
None yet
Development

No branches or pull requests

1 participant