LockFile.pm.svn-base
上传用户:market2
上传日期:2018-11-18
资源大小:18786k
文件大小:4k
源码类别:

外挂编程

开发平台:

Windows_Unix

  1. #########################################################################
  2. #  OpenKore - Lock files
  3. #
  4. #  Copryight (c) 2006 OpenKore Development Team
  5. #
  6. #  This software is open source, licensed under the GNU General Public
  7. #  License, version 2.
  8. #  Basically, this means that you're allowed to modify and distribute
  9. #  this software. However, if you distribute modified versions, you MUST
  10. #  also distribute the source code.
  11. #  See http://www.gnu.org/licenses/gpl.html for the full license.
  12. #########################################################################
  13. ##
  14. # MODULE DESCRIPTION: Lock files.
  15. #
  16. # This class provides an easy interface for lock files. A lock file is
  17. # like a mutex or critical section, but it can be used between different
  18. # processes. It's used to synchronize processes with each other.
  19. #
  20. # Lock files should not be used for file I/O: they should not be read
  21. # from or written to. On Unix it will work, but on Windows it will fail.
  22. package Utils::LockFile;
  23. use strict;
  24. use Fcntl ':flock';
  25. use Exception::Class ('Utils::LockFile::AlreadyLocked', 'Utils::LockFile::NotLocked');
  26. use Utils::Exceptions;
  27. # Cwd::realpath() dies on Windows if the file doesn't exist.
  28. # We don't want that.
  29. sub realpath {
  30. my ($file) = @_;
  31. if ($^O ne 'MSWin32' || -f $file) {
  32. require Cwd;
  33. return Cwd::realpath($file);
  34. } else {
  35. require File::Spec;
  36. return File::Spec->rel2abs($file);
  37. }
  38. }
  39. ##
  40. # Utils::LockFile->new(String file)
  41. #
  42. # Create a new Utils::LockFile object, using the specified file as lock.
  43. # The default state is unlocked.
  44. sub new {
  45. my ($class, $file) = @_;
  46. my %self = (file => realpath($file));
  47. return bless %self, $class;
  48. }
  49. sub DESTROY {
  50. my ($self) = @_;
  51. # Only unlock if process didn't fork since the lock was obtained.
  52. if ($self->locked() && $self->{pid} == $$) {
  53. $self->unlock();
  54. }
  55. }
  56. ##
  57. # boolean $Utils_LockFile->locked()
  58. #
  59. # Check whether the file is locked.
  60. sub locked {
  61. return defined $_[0]->{handle};
  62. }
  63. ##
  64. # void $Utils_LockFile->lock()
  65. # Requires: !$self->locked()
  66. #
  67. # Lock this file. If it's already locked, wait until the file is unlocked.
  68. # The lock is automatically released if this Utils::LockFile instance is
  69. # destroyed.
  70. #
  71. # Throws IOException if the lockfile cannot be opened or if
  72. # locking fails.
  73. #
  74. # Throws Utils::LockFile::AlreadyLocked if the precondition is not satisfied.
  75. sub lock {
  76. my ($self) = @_;
  77. $self->_lock(1);
  78. }
  79. ##
  80. # boolean $Utils_LockFile->tryLock()
  81. # Requires: !$self->locked()
  82. #
  83. # Attempt to lock this file. If it's already locked, returns 0. If it's
  84. # not already locked, then our lock has succeeded, and 1 is returned.
  85. # The lock is automatically released if this Utils::LockFile instance is
  86. # destroyed.
  87. #
  88. # Throws IOException if the lockfile cannot be opened or if
  89. # locking fails.
  90. #
  91. # Throws Utils::LockFile::AlreadyLocked if the precondition is not satisfied.
  92. sub tryLock {
  93. my ($self) = @_;
  94. return $self->_lock(0);
  95. }
  96. sub _lock {
  97. my ($self, $block) = @_;
  98. my $f;
  99. if (open($f, ">", $self->{file})) {
  100. my $flags = $block ? 0 : LOCK_NB;
  101. $flags |= LOCK_EX;
  102. my $result = flock($f, $flags);
  103. if ($block) {
  104. if ($result) {
  105. $self->{handle} = $f;
  106. $self->{pid} = $$;
  107. } else {
  108. close $f;
  109. IOException->throw("Cannot lock lockfile.");
  110. }
  111. } else {
  112. if ($result) {
  113. $self->{handle} = $f;
  114. return 1;
  115. } else {
  116. close $f;
  117. return 0;
  118. }
  119. }
  120. } else {
  121. IOException->throw("Cannot open lock file in write mode.");
  122. }
  123. }
  124. ##
  125. # void $Utils_LockFile->unlock()
  126. # Requires: $self->locked()
  127. #
  128. # Unlock this file.
  129. #
  130. # Throws Utils::LockFile::NotLocked if the precondition is not satisfied.
  131. sub unlock {
  132. my ($self) = @_;
  133. flock($self->{handle}, LOCK_UN);
  134. close $self->{handle};
  135. delete $self->{handle};
  136. }
  137. 1;