FWSemaphore
Semaforo distribuido pra controlar concorrencia entre threads/jobs/conexoes do Protheus. Substitui locks artesanais via tabela.
Assinatura: FWSemaphore():New(cNome) -> oSem
Retorna: object
FWSemaphore resolve um problema classico: 2 jobs paralelos tentando processar o mesmo conjunto de dados ao mesmo tempo. Usando semaforo, voce garante que so 1 executa de cada vez.
Sintaxe
Local oSem as object
oSem := FWSemaphore():New("PROCESSA_FILA_X")
If oSem:Lock(30) // 30s timeout pra adquirir
// codigo critico — so 1 execucao por vez
ProcessarFila()
oSem:Unlock()
Else
ConOut("Nao consegui lock — outro processo ja esta rodando")
EndIfCaso de uso classico: scheduler diario
User Function GeraBoletosDia()
Local oSem := FWSemaphore():New("GERA_BOLETOS_" + DToS(Date()))
Local lOk := .F.
If oSem:Lock(5)
// ja temos exclusividade — processa
Begin Sequence
ProcessaBoletos()
lOk := .T.
Recover
ConOut("Erro processando boletos")
End Sequence
oSem:Unlock()
Else
ConOut("Outra instancia ja esta gerando boletos hoje, pulando")
EndIf
Return lOkVantagens sobre lock artesanal
- Inter-process: funciona entre threads, jobs, conexoes — nao so na mesma thread
- Sem cleanup: se processo morre, semaforo libera automaticamente
- Timeout configuravel: pra evitar deadlock
- Distribuido em cluster Protheus (com configuracao certa)
Pegadinhas
- Sempre Unlock no final — preferencialmente em
End Sequencepra rodar mesmo com erro - Nome unico: dois semaforos com mesmo nome travam mutuamente. Use nome especifico pro recurso
- Timeout=0: nao espera, retorna imediato se ocupado
- Cluster: depende de configuracao certa do AppServer pra realmente sincronizar entre nodes
Parâmetros
| Nome | Tipo | Obrigatório | Descrição |
|---|---|---|---|
cNome | Character | sim | Nome unico do semaforo |
Exemplos
Lock com timeout
If oSem:Lock(10)
// executa
oSem:Unlock()
EndIf