Search This Blog

16 September 2014

Threading

I was just thinking today....

  • synchronized: The single line open at the DMV
  • thread pool: Cashiers at the grocery store
  • reentrant read/write locks: The tiny booths at Saturday Market
  • volatile: The "in-use" sign on airplane restrooms
  • concurrent collections: Open-air Farmers Market
  • FIFO: freeway on-ramp
  • LIFO: UHaul Boxes


anyone else want to contribute some?

20 August 2014

nVidia + video tearing in my IDE

I have been having some problems for the last few months where the menu items in my IDEs (plural) were tearing.  Sometimes they wouldn't popup, sometimes more than one would be highlighted, etc.

I found this article from 2 years ago which I couldn't really follow to the letter.  My nv only had one of the specified settings. I don't have ccsm installed, etc.

The ONLY change I made was:

  1. sudo su - root
  2. echo CLUTTER_PAINT=disable-clipped-redraws:disable-culling >> /etc/environment
  3. reboot

So far it seems to be working fine.

16 August 2014

Writing a custom Gradle plugin: Java + buildSrc/

I spent some time looking around at various suggestions (including on the Gradle documentation page) about how to write a custom plugin.  For my specific purpose, it was not intended to be a shared plugin - but rather one to abstract out some of the logic we are doing in our build.  I did another post on writing a Groovy plugin, here's the Java one.

To show that we are really doing a minimalist design here, let's start with a completely empty directory.

~> mkdir mytest
~> cd mytest

1. Gradle Wrapper


I personally use the Gradle Wrapper. Since the last post, I upgraded to Gradle 2.0, but the Gradle Wrapper it installs by default is not currently compatible with the Android plugin.  As such, we'll still manually define one.

Create a build.gradle file:

task wrapper(type: Wrapper) {
    gradleVersion = '1.12'
}

Run it.

~/mytest> gradle wrapper

Now that we have the wrapper installed in a fresh directory, let's look to that plugin. We'll be adding 3 Java classes and 1 properties file.

Here's what we are aiming for:

.
├── build.gradle
├── buildSrc
│   └── src
│       └── main
│           ├── java
│           │   └── org
│           │       └── eoti
│           │           └── gradle
│           │               ├── BrewinPluginExtension.java
│           │               ├── BrewinPlugin.java
│           │               └── BrewTask.java
│           └── resources
│               └── META-INF
│                   └── gradle-plugins
│                       └── brewin.properties
├── gradle
│   └── wrapper
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradlew
└── gradlew.bat


2. POJO Extension


Let's start this time by defining our POJO.  We'll create buildSrc/src/main/java/org/eoti/gradle/BrewinPluginExtension.java.

We'll add our package:

package org.eoti.gradle;

And import the Gradle API:

import org.gradle.api.*;

And create our POJO with getters/setters. 

Our complete POJO:

package org.eoti.gradle;

import org.gradle.api.*;

public class BrewinPluginExtension
{
    private String message = "Wake up!";
   
    public String getMessage(){return message;}
    public void setMessage(String message){this.message = message;}
}

3. Task


Next, we'll define our task.  Create buildSrc/src/main/java/org/eoti/gradle/BrewTask.java.

We'll add our package and imports:

package org.eoti.gradle;

import org.gradle.api.*;
import org.gradle.api.tasks.*;


Our class will extend DefaultTask.

public class BrewTask extends DefaultTask{...}

Next we'll define our task and annotate it:

@TaskAction
public void brew() {...}

In the implementation, we want to find our configuration.  If there isn't one, we'll create a default one.  Then, we'll output our message.  The complete code:

package org.eoti.gradle;

import org.gradle.api.*;
import org.gradle.api.tasks.*;

public class BrewTask extends DefaultTask
{
    @TaskAction
    public void brew() {
        BrewinPluginExtension extension = getProject().getExtensions().findByType(BrewinPluginExtension.class);
        if(extension == null)
            extension = new BrewinPluginExtension();
       
        System.out.format("%s\n", extension.getMessage());
    }
}

Note the getMessage() that we defined in our POJO.

4. Plugin


Next, we'll define our plugin.  Create buildSrc/src/main/java/org/eoti/gradle/BrewinPlugin.java.

Add your package and the Gradle import.  In my case, that is:

package org.eoti.gradle;

import org.gradle.api.*;

Our class implements Plugin<Project> which means we have:

@Override
public void apply(Project project){ ... }

We will specify two things in this function.

First, an extension to allow parameters to be passed in:

project.getExtensions().create("brewin", BrewinPluginExtension.class);

The name "brewin" is the name of the configuration block.

Second, a task to be added once this plugin is applied:

project.getTasks().create("brew", BrewTask.class);

That 'brew' is the @TaskAction name from above.

The complete plugin:

package org.eoti.gradle;

import org.gradle.api.*;

public class BrewinPlugin implements Plugin
{
    @Override
    public void apply(Project project)
    {
        project.getExtensions().create("brewin", BrewinPluginExtension.class);
        project.getTasks().create("brew", BrewTask.class);
    }
}


5. Properties


Now, we need to add the properties file using the same configuration name we chose above.  In this case, buildSrc/src/main/resources/META-INF/gradle-plugins/brewin.properties.

It contains one line that points to our plugin implementation:

implementation-class=org.eoti.gradle.BrewinPlugin

Ok, we're almost done.

6. Apply it


In your top-level build.gradle, specify that we want to apply our new plugin by adding this to the top:

apply plugin: org.eoti.gradle.BrewinPlugin

And then from the command line, call the task we defined earlier:

~/mytest> ./gradlew brew


That's great!  But, why did we create a configuration parameter if we aren't going to use it?

Add this to your top-level build.gradle:

brewin{
    message = "Make another pot!"
}

And then re-run it:

~/mytest> ./gradlew brew

There you go.  You can add additional parameters, additional Java logic, etc.

Writing a custom Gradle plugin: Groovy + buildSrc/

I spent some time looking around at various suggestions (including on the Gradle documentation page) about how to write a custom plugin.  For my specific purpose, it was not intended to be a shared plugin - but rather one to abstract out some of the logic we are doing in our build.  I'll probably actually do another post on writing a Java plugin, but for now let's try the Groovy one.

To show that we are really doing a minimalist design here, let's start with a completely empty directory.

~> mkdir mytest
~> cd mytest

I personally use the Gradle Wrapper. Gradle 1.6 is installed on the system, but once the Gradle Wrapper takes over it's ignored.

Create a build.gradle file:

task wrapper(type: Wrapper) {
    gradleVersion = '1.12'
}

Run it.

~/mytest> gradle wrapper

Now that we have the wrapper installed in a fresh directory, let's look to that plugin.  We'll be adding 1 groovy file and 1 properties file.

Here's what we are aiming for:

.
├── build.gradle
├── buildSrc
│   └── src
│       └── main
│           ├── groovy
│           │   └── GroovinPlugin.groovy
│           └── resources
│               └── META-INF
│                   └── gradle-plugins
│                       └── groovin.properties
├── gradle
│   └── wrapper
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradlew
└── gradlew.bat

In buildSrc/src/main/groovy/ create your new plugin file. In my case, it was called GroovinPlugin.groovy.

We'll still put a Java-style package at the top, even though the source file was not contained in a Java-style package directory. IE: I used package org.eoti.gradle even though the directory was not org/eoti/gradle.

We need to import the Gradle API.

import org.gradle.api.*
import org.gradle.api.plugins.*

Our class (same name as the file) implements Plugin<Project> which means we have:

void apply(Project project) { ... }

In my case I specified two things in this function.

First, an extension to allow parameters to be passed in:

project.extensions.create("groovin", GroovinPluginExtension)

We'll discuss that GroovinPluginExtension in a moment.  The name "groovin" is the name of the configuration block.

Secondly, I specified a task to be added once this plugin is applied:

project.task('groove') << {
    println project.groovin.message
}

That 'groovin' is the configuration name from above. 'message' is the parameter name defined inside GroovinPluginExtension.  The GroovinPluginExtension is just another class defined in the same file (not an inner class though) providing a POGO. A POGO is basically a POJO that automatically creates the getters and setters for you.

In this case, we define a String called 'message', as such:

class GroovinPluginExtension {
    def String message = 'We be groovin\''
}

Put all together, the GroovinPlugin.groovy looks like:

package org.eoti.gradle;

import org.gradle.api.*
import org.gradle.api.plugins.*

class GroovinPlugin implements Plugin<Project> {
    void apply(Project project) {
        project.extensions.create("groovin", GroovinPluginExtension)
        project.task('groove') << {
            println project.groovin.message
        }
    }
}

class GroovinPluginExtension {
    def String message = 'We be groovin\''
}

Pretty small, right?

Now, we need to add the properties file using the same configuration name we chose above.  In this case, buildSrc/src/main/resources/META-INF/gradle-plugins/groovin.properties.

It contains one line that points to our plugin implementation:

implementation-class=org.eoti.gradle.GroovinPlugin

Ok, we're almost done.

In your top-level build.gradle, specify that we want to apply our new plugin by adding this to the top:

apply plugin: org.eoti.gradle.GroovinPlugin

And then from the command line, call the task we defined earlier:

~/mytest> ./gradlew groove

That's great!  But, why did we create a configuration parameter if we aren't going to use it?

Add this to your top-level build.gradle:

groovin{
    message = "We be jammin'"
}

And then re-run it:

~/mytest> ./gradlew groove

There you go.  You can add additional parameters, additional Groovy logic, etc.