Rework SoftRefFilesCache locking (#154)

* SoftRefFilesCache: no ReferenceQueue timeout, sleep indefinitely

Waking up once a second is just a waste of CPU time.  Let
ReferenceQueue.remove() only wake up if there's something to do (or if
the thread got interrupted).

* SoftRefFilesCache: eliminate the requestEnd flag

The Thread class keeps track for us already, and if it's interrupted,
we'll catch InterruptedException and quit the thread.

* SoftRefFilesCache: fix ReentrantLock usage in {start,end}Thread()

Can't use the "synchronized" keyword on a Lock; this will only lock
the java.lang.Object, but not the Lock.

This wrong usage was added by commit f09035290b1 (SVN r1704932).

* SoftRefFilesCache: add missing lock to removeFile()

The API documentation of close(FileSystem) requires that the caller
holds the lock, but removeFile() didn't do that.

* SoftRefFilesCache: require lock while calling removeFile(FileSystemAndNameKey)

This allows merging the lock with the caller, fixing a race condition
in removeFile(FileSystem,FileName).

* SoftRefFilesCache: require lock while calling getOrCreateFilesystemCache()

It is an illusion to believe that not requiring the lock would be
faster, because all callers will obtain the lock right after
getOrCreateFilesystemCache() returns.

As a wanted side effect, this also fixes a time-of-check-time-of-use
bug: if the fileSystemCache becomes non-empty by another thread
between the isEmpty() and the get() call (with removeFile() calls by
yet another thread), the SoftRefReleaseThread will never be started.

* SoftRefFilesCache: don't use ConcurrentMap

Now that all accesses to fileSystemCache happen while the lock is
held, we don't need another layer of synchronization.

* SoftRefFilesCache: eliminate "volatile" on softRefReleaseThread

That "double checked locking" in startThread() is rather pointless,
because the overhead saved by not locking never materializes.
startThread() is only ever called when there is no thread, and
optimizing for a corner case with a data race isn't worth the
complexity.  So let's just do everything inside the lock and remove
"volatile".

* SoftRefFilesCache: move endThread() call inside the lock

This avoids locking the Lock twice, because the two lock sections are
merged.

* SoftRefFilesCache: require lock for startThread(), endThread()

All callers already do that, this just documents the fact and removes
the explicit lock()/unlock() calls from those methods.

* SoftRefFilesCache: move code to removeFile(Reference)

* SoftRefFilesCache: eliminate ReentrantLock, use "synchronized"

This class uses no special ReentrantLock/Lock feature, it's just basic
thread synchronization.  Using "synchronized" is easier to use and
less error prone.
1 file changed
tree: b9b9d0aa66ed5dc329d436272ed8fe6cb7c90cdd
  1. .github/
  2. commons-vfs2/
  3. commons-vfs2-distribution/
  4. commons-vfs2-examples/
  5. commons-vfs2-jackrabbit1/
  6. commons-vfs2-jackrabbit2/
  7. commons-vfs2-sandbox/
  8. src/
  9. .gitignore
  10. .travis.yml
  11. BUILDING.txt
  12. checkstyle-suppressions.xml
  13. checkstyle.properties
  14. checkstyle.xml
  15. CONTRIBUTING.md
  16. findbugs-exclude-filter.xml
  17. LICENSE.txt
  18. NOTICE.txt
  19. pom.xml
  20. README.md
  21. RELEASE-NOTES.txt
  22. SECURITY.md
README.md

Apache Commons VFS Project

Travis-CI Status GitHub Actions Status Coverage Status Maven Central Javadocs

Apache Commons VFS is a Virtual File System library.

Documentation

More information can be found on the Apache Commons VFS Project homepage. The Javadoc can be browsed. Questions related to the usage of Apache Commons VFS Project should be posted to the user mailing list.

Where can I get the latest release?

You can download source and binaries from our download page.

Alternatively you can pull it from the central Maven repositories:

<dependency>
  <groupId>org.apache.commons</groupId>
  <artifactId>commons-vfs2</artifactId>
  <version>2.7.0</version>
</dependency>

Contributing

We accept Pull Requests via GitHub. The developer mailing list is the main channel of communication for contributors. There are some guidelines which will make applying PRs easier for us:

  • No tabs! Please use spaces for indentation.
  • Respect the code style.
  • Create minimal diffs - disable on save actions like reformat source code or organize imports. If you feel the source code should be reformatted create a separate PR for this change.
  • Provide JUnit tests for your changes and make sure your changes don't break any existing tests by running mvn clean test.

If you plan to contribute on a regular basis, please consider filing a contributor license agreement. You can learn more about contributing via GitHub in our contribution guidelines.

License

This code is under the Apache Licence v2.

See the NOTICE.txt file for required notices and attributions.

Donations

You like Apache Commons VFS Project? Then donate back to the ASF to support the development.

Additional Resources