Go to Post The bottom line is this program means the world to me ,and the friends i hold dear that feel the same way....I believe it changes lives and outlooks on reality. - D@ve [more]
Home
Go Back   Chief Delphi > Technical > Programming > Java
CD-Media   CD-Spy  
portal register members calendar search Today's Posts Mark Forums Read FAQ rules

 
Reply
Thread Tools Rate Thread Display Modes
  #1   Spotlight this post!  
Unread 05-31-2012, 11:50 PM
joelg236 joelg236 is offline
4334 Retired Mentor & Alumni
AKA: Joel Gallant
no team
Team Role: Mentor
 
Join Date: Dec 2011
Rookie Year: 2012
Location: Calgary
Posts: 733
joelg236 has a reputation beyond reputejoelg236 has a reputation beyond reputejoelg236 has a reputation beyond reputejoelg236 has a reputation beyond reputejoelg236 has a reputation beyond reputejoelg236 has a reputation beyond reputejoelg236 has a reputation beyond reputejoelg236 has a reputation beyond reputejoelg236 has a reputation beyond reputejoelg236 has a reputation beyond reputejoelg236 has a reputation beyond repute
Concurrency and multiple commands

Code:
    private int currentCommand;
    private void runConcurrentCommands(final Vector<CommandBase> v) {
        Thread thread = null;
        for(currentCommand = 0; currentCommand < v.size(); currentCommand++) {
            System.out.println("Current = "+currentCommand);
            thread = new Thread(new Runnable() {
                @Override
                public void run() {
                    System.out.println("Running = "+currentCommand);
                    CommandBase.getInstance().run(v.get(currentCommand));
                }
            });
            thread.start();
        }
        try {
            thread.join(1000);
        } catch (InterruptedException ex) {
            
        } catch (NullPointerException ex) {
            
        }
    }
Why does this give me the output of
Code:
run:
Sequential: team4334.code.commands.ExampleCommand@5b86d4c1
Run
Sequential: team4334.code.commands.ExampleCommand@70f9f9d8
Run
Sequential: team4334.code.features.Feature$1@2b820dda
Concurrent: team4334.code.commands.modes.ExampleMode@675b7986
Concurrent: team4334.code.commands.ExampleCommand@2687816d
Concurrent: team4334.code.commands.modes.ExampleMode@a422ede
Current = 0
Current = 1
Running = 1
Current = 2
Running = 2
Run
Run
Running = 3
Exception in thread "Thread-2" java.lang.ArrayIndexOutOfBoundsException: Array index out of range: 3
Sequential: team4334.code.commands.modes.ExampleMode@7ca83b8a
Run
	at java.util.Vector.get(Vector.java:721)
	at team4334.code.features.Feature$2.run(Feature.java:113)
	at java.lang.Thread.run(Thread.java:679)
BUILD SUCCESSFUL (total time: 3 seconds)
Is this a logic error or a concurrency error? In either case, what would be the best way to fix it?

I feel like the new Runnable is changing the value of currentCommand even before the for loop notices it is out of the range. If that is the case, how could I solve this problem? I have tried making the variable volatile (With the same result) and making the methods synchronized. I'm stumped.
__________________
All opinions are my own.
Reply With Quote
  #2   Spotlight this post!  
Unread 06-01-2012, 10:04 AM
Mr. Lim Mr. Lim is offline
Registered User
AKA: Mr. Lim
no team
Team Role: Leadership
 
Join Date: Jan 2004
Rookie Year: 1998
Location: Toronto, Ontario
Posts: 1,125
Mr. Lim has a reputation beyond reputeMr. Lim has a reputation beyond reputeMr. Lim has a reputation beyond reputeMr. Lim has a reputation beyond reputeMr. Lim has a reputation beyond reputeMr. Lim has a reputation beyond reputeMr. Lim has a reputation beyond reputeMr. Lim has a reputation beyond reputeMr. Lim has a reputation beyond reputeMr. Lim has a reputation beyond reputeMr. Lim has a reputation beyond repute
Re: Concurrency and multiple commands

Concurrency.

Your for loop is completing and incrementing currentCommand before your threads are actually starting.

Despite calling thread.start() - they don't actually have to start "right away."

This is why you also never see "Running = 0".

When your 1st spawned thread finally runs, the for loop has already completed, and currentCommand was incremented to 1 before the thread even ran...

A hack fix would be to add a thread.join(???) at the end of your for loop (after thread.start(), where ??? is just long enough to start your Command.

Not pretty, but it'll likely work.

Even better, pass currentCommand as a parameter to your threads... something like:
http://stackoverflow.com/questions/8...-a-java-thread

Good luck!
__________________
In life, what you give, you keep. What you fail to give, you lose forever...

Last edited by Mr. Lim : 06-01-2012 at 10:08 AM.
Reply With Quote
  #3   Spotlight this post!  
Unread 06-01-2012, 10:19 AM
Mr. Lim Mr. Lim is offline
Registered User
AKA: Mr. Lim
no team
Team Role: Leadership
 
Join Date: Jan 2004
Rookie Year: 1998
Location: Toronto, Ontario
Posts: 1,125
Mr. Lim has a reputation beyond reputeMr. Lim has a reputation beyond reputeMr. Lim has a reputation beyond reputeMr. Lim has a reputation beyond reputeMr. Lim has a reputation beyond reputeMr. Lim has a reputation beyond reputeMr. Lim has a reputation beyond reputeMr. Lim has a reputation beyond reputeMr. Lim has a reputation beyond reputeMr. Lim has a reputation beyond reputeMr. Lim has a reputation beyond repute
Re: Concurrency and multiple commands

Also, WPILib has support for concurrent Commands using CommandGroups.

It's documented in the WPILib cookbook.

Search for the AddParallel and AddSequential methods.

It's possible you might be trying to re-invent something that already works pretty well!
__________________
In life, what you give, you keep. What you fail to give, you lose forever...
Reply With Quote
  #4   Spotlight this post!  
Unread 06-01-2012, 02:11 PM
joelg236 joelg236 is offline
4334 Retired Mentor & Alumni
AKA: Joel Gallant
no team
Team Role: Mentor
 
Join Date: Dec 2011
Rookie Year: 2012
Location: Calgary
Posts: 733
joelg236 has a reputation beyond reputejoelg236 has a reputation beyond reputejoelg236 has a reputation beyond reputejoelg236 has a reputation beyond reputejoelg236 has a reputation beyond reputejoelg236 has a reputation beyond reputejoelg236 has a reputation beyond reputejoelg236 has a reputation beyond reputejoelg236 has a reputation beyond reputejoelg236 has a reputation beyond reputejoelg236 has a reputation beyond repute
Re: Concurrency and multiple commands

Quote:
It's possible you might be trying to re-invent something that already works pretty well!
Funny thing is that that is exactly what I'm trying to do.

Quote:
A hack fix would be to add a thread.join(???) at the end of your for loop (after thread.start(), where ??? is just long enough to start your Command.
I feel like that is not a sufficiently consistent way of doing what I am trying to do. (As well as almost eliminating the purposes of doing it - that will either not wait long enough or make the commands run in sequence (and not concurrently))

My biggest issue is that when I tried to do this :
Code:
    private void runConcurrentCommands(final Vector<CommandBase> v) {
        currentCommand = 0;
        Thread thread = null;
        System.out.println("Current = "+currentCommand);
        thread = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("Running = "+currentCommand);
                CommandBase.getInstance().run(v.get(currentCommand));
                currentCommand++;
            }
        });
        thread.start();
    }
it did not change the output.

To me, that would eliminate the problem by only incrementing the commandCount AFTER the command has run (And not incrementing it beforehand on the first run).
__________________
All opinions are my own.
Reply With Quote
  #5   Spotlight this post!  
Unread 06-01-2012, 02:13 PM
joelg236 joelg236 is offline
4334 Retired Mentor & Alumni
AKA: Joel Gallant
no team
Team Role: Mentor
 
Join Date: Dec 2011
Rookie Year: 2012
Location: Calgary
Posts: 733
joelg236 has a reputation beyond reputejoelg236 has a reputation beyond reputejoelg236 has a reputation beyond reputejoelg236 has a reputation beyond reputejoelg236 has a reputation beyond reputejoelg236 has a reputation beyond reputejoelg236 has a reputation beyond reputejoelg236 has a reputation beyond reputejoelg236 has a reputation beyond reputejoelg236 has a reputation beyond reputejoelg236 has a reputation beyond repute
Re: Concurrency and multiple commands

Sorry about that obvious bug in the code up there. I added a loop to go through the commands, but still no result.
__________________
All opinions are my own.
Reply With Quote
  #6   Spotlight this post!  
Unread 06-01-2012, 03:12 PM
joelg236 joelg236 is offline
4334 Retired Mentor & Alumni
AKA: Joel Gallant
no team
Team Role: Mentor
 
Join Date: Dec 2011
Rookie Year: 2012
Location: Calgary
Posts: 733
joelg236 has a reputation beyond reputejoelg236 has a reputation beyond reputejoelg236 has a reputation beyond reputejoelg236 has a reputation beyond reputejoelg236 has a reputation beyond reputejoelg236 has a reputation beyond reputejoelg236 has a reputation beyond reputejoelg236 has a reputation beyond reputejoelg236 has a reputation beyond reputejoelg236 has a reputation beyond reputejoelg236 has a reputation beyond repute
Re: Concurrency and multiple commands

Solved.

For the benefit of anyone that might have been curious as to the solution or are looking around for ways to do this - here it is.

Code:
private int currentCommands;
    private synchronized void runConcurrentCommands(final Vector<CommandBase> v) {
        try {
            concurrentCommandsFinished = false;
            Thread[] threads = new Thread[v.size()];
            for(int x = 0; x < v.size(); x++) {
                currentCommands = x;
                threads[x] = new Thread(new Runnable() {
                    public final int commandNum = currentCommands;
                    @Override
                    public void run() {
                        System.out.println("Running "+commandNum);
                        //CommandBase.getInstance().run(v.get(commandNum));
                    }
                });
            }
            for(int x = 0; x < threads.length; x++) {
                threads[x].start();
            }
            for(int x = 0; x < threads.length; x++) {
                while(threads[x].isAlive()) {
                    concurrentCommandsFinished = false;
                }
            }
            concurrentCommandsFinished = true;
        }catch(NullPointerException ex) {
            
        }
    }
    
    private int lastThread = 0;
    private boolean concurrentCommandsFinished = false;
    private synchronized void waitForConcurrentCommands() throws InterruptedException {
        while(!concurrentCommandsFinished) {
            Thread.sleep(1);
        }
    }

    public void enable() {
        try {
            this.interupted = false;
            boolean adding = false;
            Vector<CommandBase> concurrentCommands = new Vector<CommandBase>(1, 1);
            for(int x = 0; x < commands.size(); x++) {
                if(commandTypes.get(x).equals("Sequencial")) {
                    if(adding) {
                        runConcurrentCommands(concurrentCommands);
                        concurrentCommands = new Vector<CommandBase>(1, 1);
                        adding = false;
                        try {
                            waitForConcurrentCommands();
                        } catch (InterruptedException ex) {
                            
                        }
                    }
                    System.out.println("Sequencial command "+x);
                    CommandBase.getInstance().run(commands.get(x));
                }else if(commandTypes.get(x).equals("Concurrent")) {
                    adding = true;
                    concurrentCommands.add(commands.get(x));
                }
            }
            if(adding) {
                runConcurrentCommands(concurrentCommands);
                adding = false;
            }
            
        }catch(NullPointerException ex) {
            
        }
    }
I created an array of threads - and did not run them until after they are all created. With this array, I needed a way to keep the variable of currentcommand in the state it was during creation of the object. That is why I have the
Quote:
public final int commandNum = currentCommands;
in there.

In terms of running it all, I included the rest of the current code that I have. There is a portion that waits for an array of concurrent commands to finish before doing another sequencial command. Basically, this has almost all of the features of the CommandGroup class in WPI, while not using Scheduler or any WPI libraries (So it can be ported).

Again, thank you Mr.Lim for your help
__________________
All opinions are my own.
Reply With Quote
Reply


Thread Tools
Display Modes Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Forum Jump


All times are GMT -5. The time now is 07:51 AM.

The Chief Delphi Forums are sponsored by Innovation First International, Inc.


Powered by vBulletin® Version 3.6.4
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd.
Copyright © Chief Delphi