gbadev.org forum archive

This is a read-only mirror of the content originally found on forum.gbadev.org (now offline), salvaged from Wayback machine copies. A new forum can be found here.

OffTopic > Java precompiler

#119056 - Mr Snowflake - Mon Feb 19, 2007 11:45 am

I need something in the likes of:
Code:
#ifndef PARALLELIZE
//some code for starting threads
#else
//some other non thread code
#endif

for java. Does is it possible without any extensions or external apps?
_________________
http://www.mrsnowflake.be

#119058 - keldon - Mon Feb 19, 2007 12:04 pm

Huh? When can't you start new threads in Java?

#119059 - Mr Snowflake - Mon Feb 19, 2007 12:09 pm

It's for a school project and so I want to be sure the algorithm works without threading. But when the algorithm works I want to recode the algorithm to use threading, but I still need the previous, non-threading, algorithm to be certain the project still works if the multi-threaded algorithm would fail or if I can't get it to work on time.
_________________
http://www.mrsnowflake.be

#119063 - sgeos - Mon Feb 19, 2007 12:27 pm

You could use a class variable and a standard if statment.

-Brendan

#119064 - keldon - Mon Feb 19, 2007 12:27 pm

Code:
//Config.java
public final class Config {
   public boolean isMultithreading() {
      // insert decision code here, could read from a variable or from a config file
   }
}


Alternatively you could just use a public final static boolean in a configuration class. There is also a class somewhere in Java specifically for using a .ini style config file.

EDIT: I got ninja'd ^_^

#119065 - Mr Snowflake - Mon Feb 19, 2007 12:32 pm

sgeos wrote:
You could use a class variable and a standard if statment.

-Brendan
That was indeed one of the options, but I thought maybe there was a 'better' way... Because this way is also possible in C but no one uses it.
_________________
http://www.mrsnowflake.be

#119067 - sgeos - Mon Feb 19, 2007 12:36 pm

The problem with Java, is that it is (in theory) compile once, run anywhere. I don't think compile time macros are as important in such an environment.

-Brendan

#119069 - Mr Snowflake - Mon Feb 19, 2007 12:47 pm

While debugging they can be very interesting, whether or not being in a run everywhere environment, because your average user is interested in a program which will crash when he, accidentally, modifies the ini (in the .ini scenario). And removing the buggy code for every release/update isn't really the way you want to go...
_________________
http://www.mrsnowflake.be

#119091 - gauauu - Mon Feb 19, 2007 4:06 pm

I agree. I write java code at work all day, and I can't tell you how badly I wish there was a precompiler. I guess the designers of java wanted to avoid all the nasty crap that macros in C have been known to do (like trying to turn C into pascal).

That being said, if you really needed the functionality, you could run your java code through the C preprocessor before compiling. Or write your own simple pre-processor if you don't have access to the standard C one for this project.

#119093 - Mr Snowflake - Mon Feb 19, 2007 4:16 pm

That's probably not a too bad idea, but then I (almost) need a makefile for my java project, and I dunno if the profs will like it... Have to ask my project companion.
_________________
http://www.mrsnowflake.be

#119298 - sgeos - Wed Feb 21, 2007 6:11 pm

On a certain level, using the C preprocessor is goofy. On another level, if it gets the job done...

-Brendan

#119348 - josath - Thu Feb 22, 2007 3:18 am

Speaking of goofy, I've heard of people using the C preprocessor on their Actionscript source code.

#119359 - sgeos - Thu Feb 22, 2007 11:54 am

I've used it on HTML. That was goofy.

-Brendan

#119362 - keldon - Thu Feb 22, 2007 12:29 pm

There really is no need to use a pre processor in your case. Your program should not be able to crash from an incorrect .ini file; if the file is invalid then load defaults and inform the user whilst giving them the option to reset the file (or invalid entries) to the defaults or the last usable settings.

#119370 - Mr Snowflake - Thu Feb 22, 2007 2:09 pm

keldon wrote:
There really is no need to use a pre processor in your case. Your program should not be able to crash from an incorrect .ini file; if the file is invalid then load defaults and inform the user whilst giving them the option to reset the file (or invalid entries) to the defaults or the last usable settings.
What I meant was, when the user changed the ini value to multi threading, so he winded up with an unstable program.
Just to be clear: I'll probably use a ini file, or Config class, but I was hypothetically speaking about what you would do when this would pop-up in a commercial program. In that case I believe the precompiler manner is much better!
_________________
http://www.mrsnowflake.be

#119376 - keldon - Thu Feb 22, 2007 3:27 pm

If you use a precompiler then you would have to compile different versions for both multithreading and single threaded. You can compile different versions without using a precompiler - either recompile with the static variable changed (making note of this in the name) or use one of two different classes to execute. Either way it really does not need to be complicated at all to allow the use of two different switches of that nature. And if you are packing a jar file, then just set the jar file to execute MultithreadMain instead of SinglethreadMain!

#119378 - sgeos - Thu Feb 22, 2007 3:43 pm

You could use a wrapper class with a boolean variable to manage single and multithreaded versions of your class. (3 classes and 1 interface.)

-Brendan

#119384 - naleksiev - Thu Feb 22, 2007 5:10 pm

I have 3 solutions for you

1. If you have variable

static final boolean PARALLELIZE = ???;

the non used code will be completely removed after compilation (if not it will be for sure after obfuscation).

2. If you want to have some additional macros like

#define SHIFT 12
#define FIXED_INIT(n, d) ((n << SHIFT) / d)

you can use the cpp compiler to compile with parameters that will just process the preprocessing instructions. After this you can run the javac. It will need a small compilation script and you will not be able to debug.

3. I think J# support #define, #ifdef, #ifndef so you can use it as a IDE to edit debug and use solution 2 if you need a real java compilation at the end.

#119389 - Mr Snowflake - Thu Feb 22, 2007 5:16 pm

Well 1. is almost as good as a define I guess. 2. is kinda logic and 3. is not really an option (unless j# compiler is in mono, and it is java compatible because we need to do it in Java, but thanks ;)).

I'll go with the static final boolean. Thanks everybody for answering!
_________________
http://www.mrsnowflake.be

#120166 - Mr Snowflake - Thu Mar 01, 2007 12:36 pm

Thanks guys for the answers, but I stepped away from this problem by making the 'crucial' function part of a plugin (well kind of). I have the program load a class through reflection because this way, the program could also do other things instead of only documenting Java classes through reflection. This way I can make my threaded code a plugin and load which ever I want.

Well maybe I'm not doing it quite right with the plug-in loading, so maybe someone here know how to 'officially' do it. ATM I made a static class with only 1 function (which should be enough for my purpose) and I load the class with the Class c = class.forName(pluginName); and then instantiating and getMethoding the wanted function. Is this correctly for making plugins in Java or could it be done much more easy? (lots of exception handling is involved this way).
_________________
http://www.mrsnowflake.be

#120169 - ps2aich - Thu Mar 01, 2007 1:34 pm

As very general pattern, such things can be done via an 'Factory' in Java.

This means you define an interface for your purpose (e.g. IMyFunctionality).
Then you define a factory (usually a class with only static methods, or a singleton).
You then asks the factory for the actual implementation of your interface.
Which implementation you actually get delivered is either dependent of a parameter or e.g. a system property (System.getProperty("myFunctionality")).

Example by parameter:
Code:

IMyFunctionality obj = XYZFactory.getMyFunctionality(IMyFunctionality.SINGLETHREADED);


Example by system property:
Code:

Start your JavaVM with '-vmargs -DmyFunctionality=multithreaded'.

IMyFunctionality obj = XYZFactory.getMyFunctionality();


Your rest program only works on this interface, and you can exchange the acctual implementation. Your Factory class has to decide, which implementation actually is used.

That depends that the concept of an interface in java is familiar for you.
The interface defines the methods you need. And your implementation classes then must 'implement' this Interface:
Code:


public interface IMyFunctionality
{
   public String getID();

   public int computeWhatever(int a,int b);
}

public class SingleThreadedXYZ implements IMyFunctionality
{
   public SingleThreadedXYZ()
   {
   }

  public String getID()
  {
     return "SingleThreaded";
  }

  public int computeWhatever(int a, int b)
  {
     return a + b;
  }
}

#120176 - gauauu - Thu Mar 01, 2007 3:59 pm

ps2aich wrote:
As very general pattern, such things can be done via an 'Factory' in Java.


Also, avoiding reflection when you can help it tends to be a good thing. There are a number of application-launching frameworks out there (eclipse, webstart, etc) that do slightly funky things with the classpath. I've used a few libraries that depend on a lot of reflection and classloading tricks that start failing when you introduce them into an environment with other nasty classloading tricks. (i.e. JasperReports custom reports loading when launching an Eclipse RCP app via webstart)

#120181 - Mr Snowflake - Thu Mar 01, 2007 5:10 pm

Yeah, I know reflection tends to be slow sometimes. So could someone please go into a little more detail on ps2aich's method? I know factory classes and plugin stuff in c/c++, but I'm not very familiar with the java command-line options and other java stuff.
_________________
http://www.mrsnowflake.be

#120184 - gauauu - Thu Mar 01, 2007 6:07 pm

So you already understand how a factory generally works, right?

Java has system properties, which are not so different from a global map of Strings to Objects, so you can use this to keep track of all sorts of things about the global options for your application.

Properties can be set from the command line:

Code:
-vmargs -DmyFunctionality=multithreaded

Sets the property "myFunctionality" to "multithreaded".

Or via code:

Code:
System.setProperty("myFunctionality", "multithreaded")


And they can be read back the same way:

Code:
System.getProperty("myFunctionality")


returns "multithreaded" (or whatever it was set to in this instance)

So in your XYZFactory, you could check for the "myFunctionality" property, and create the right object based on it's value:

Code:

public class XYZFactory {

   /**
    * Returns an IMyFunctionality object either single-threaded or
    * multi-threaded, depending on the parameter passed in
    */
   public static IMyFunctionality getMyFunctionality(String threadType)
   {
      if (threadType.equals("multithreaded")) {
         return new MultiThreadedMyFunctionality();
      } else {
         return new SingleThreadedMyFunctionality();
      }
   }

   /**
    * Returns the correct IMyFunctionality based on the system property
    * /
   public static IMyFunctionality getMyFunctionality()
   {
      return getMyFunctionality(System.getProperty("myFunctionality"));
   }

}


Of course, you'd probably want to do better error checking and whatnot in the factory. But this is the general idea.

#120185 - Mr Snowflake - Thu Mar 01, 2007 6:15 pm

That's a nice option, but this isn't really a plugin is it? If it isn't it's the best (read prettiest) way of the the wanted (single/multi threading) code to work.
_________________
http://www.mrsnowflake.be

#120195 - gauauu - Thu Mar 01, 2007 6:45 pm

No, it's not a plugin. To do something as an actual plugin, you need to dive into reflection. You can still do something similar to this, but using reflection to dynamically load the right classes

#120197 - Mr Snowflake - Thu Mar 01, 2007 7:21 pm

Thanks. When using a factory interface, do I still need to getMethod the methods I want to use, when loading the plugin through reflection? Or am I than able to just call the function:
Code:

MyInterface obj = reflection loaded MyPlugin
obj.someMethod();

or should I do:
Code:

MyInterface obj = reflection loaded MyPlugin
reflection load some method and handle lots and lots of exceptions :)

_________________
http://www.mrsnowflake.be

#120206 - sgeos - Thu Mar 01, 2007 8:06 pm

Mr Snowflake wrote:
Thanks. When using a factory interface, do I still need to getMethod the methods I want to use, when loading the plugin through reflection?

Why do you want to use a factory and reflection?

-Brendan

#120212 - Mr Snowflake - Thu Mar 01, 2007 8:36 pm

I dunno, through reflection I currently load a plugin and I was hoping I could drop the reflection getMethod part.
_________________
http://www.mrsnowflake.be

#120217 - gauauu - Thu Mar 01, 2007 9:41 pm

Mr Snowflake wrote:
Thanks. When using a factory interface, do I still need to getMethod the methods I want to use, when loading the plugin through reflection? Or am I than able to just call the function:
Code:

MyInterface obj = reflection loaded MyPlugin
obj.someMethod();



Yes, you can call it like this.


Quote:
I dunno, through reflection I currently load a plugin and I was hoping I could drop the reflection getMethod part.


But the real question is why do you want to use a plugin in the first place? If it's a question of using or not using the multithreaded code (like you talked about in the first place), then you can dynamically choose which object to use at runtime without using plugins.

#120227 - sgeos - Thu Mar 01, 2007 10:17 pm

You don't need a plugin.
Code:
myFactory.isMultithreaded( true  );
myFactory.isMultithreaded( false );
myObject = myFactory.newObject();

Or, if you know how to do it:
Code:
myObject = myFactory.isMultithreaded( true  ).newObject();
myObject = myFactory.isMultithreaded( false ).newObject();

-Brendan

#120229 - Mr Snowflake - Thu Mar 01, 2007 10:19 pm

gauauu wrote:
But the real question is why do you want to use a plugin in the first place? If it's a question of using or not using the multithreaded code (like you talked about in the first place), then you can dynamically choose which object to use at runtime without using plugins.
That was the initial idea, but now I want to be able to make another class so not only JavaClasses can be handled but also other stuff. And thus needing a plugin!
_________________
http://www.mrsnowflake.be

#120306 - ps2aich - Fri Mar 02, 2007 3:39 pm

Mr Snowflake wrote:
Thanks. When using a factory interface, do I still need to getMethod the methods I want to use, when loading the plugin through reflection? Or am I than able to just call the function:
Code:

MyInterface obj = reflection loaded MyPlugin
obj.someMethod();

or should I do:
Code:

MyInterface obj = reflection loaded MyPlugin
reflection load some method and handle lots and lots of exceptions :)


If your loaded class implements the interface, you do not need reflection,
since your program is compiled against the interface and calls the
interface methods directly.

A Java Interface simply separates the interface of an object (in this case the methods of an object) from its actual implementation.

The only dependency you have is that the loaded class must be built
against the same version of the interface, that means if you change the interface, you also must compile the loaded plugin against.

If you have the requirement that your interface changes often, you
could design a more loose coupled interface, that uses generic datastructes like a map.
Example:
Instead of a very strong coupled interface method
Code:

public int compute(int argumentA, int argumentA,boolean someCondition);

you could use a compute method of following form:
Code:

public IResult compute(Map arguments,IContext context);


So arguments and context can change without the need to change the Interface itself.

In my opinion, the difference between a plugin and a factory created object is not sharp, but more a matter of interface design (or a set of interfaces).

If you cannot bring your requirements into match with interfaces, and still need reflection, simply encapsulate your reflection usages into some parametrizable utility methods and specifiy some conventions of the used methods.

By the way, to get the way back to GBA and DS development, if you look into the sources of the Chishm's libfat, the defined structure for the different fat implementations is nothing else like an interface, but realised with the possiblities of C.

#121091 - Mr Snowflake - Thu Mar 08, 2007 8:47 pm

For the record: It works nicely with the Interface. No more nasty reflection for loading the methods. Only when loading the class (obviously).
_________________
http://www.mrsnowflake.be