For two methods to call each other: how to prevent an infinite loop?

I have two classes (A and B) that depend on each other in the following sense: Each class has a method that performs an action.
The action of each class depends on the action of another class.

So, if the user invokes an action of class A, he should automatically invoke the action of class B.
The same goes for the other. But an infinite loop should be avoided.

I found code that addresses this issue, but it seems to be a bit dumb: an endless loop is prevented by locking .

import java.util.concurrent.locks.*;
import static java.lang.System.*;
import org.junit.*;

public class TEST_DependentActions {

  static class A {
    private B b = null;
    private final ReentrantLock actionOnBLock = new ReentrantLock();

    public void setB(B b) {
      this.b = b;
    }

    public void actionOnB() {
      if (!actionOnBLock.isLocked()) {
        actionOnBLock.lock();
        b.actionOnA();
        actionOnBLock.unlock();
      }
    }
  }

  static class B {
    private A a = null;
    private final ReentrantLock actionOnALock = new ReentrantLock();

    public void setA(A a) {
      this.a = a;
    }

    public void actionOnA() {
      if (!actionOnALock.isLocked()) {
        actionOnALock.lock();
        a.actionOnB();
        actionOnALock.unlock();
      }
    }
  }

  @Test
  public void test1()
      throws Exception {

    out.println("acting on class A first:");

    A a = new A(); B b = new B();
    a.setB(b);     b.setA(a);

    a.actionOnB();
  }

  @Test
  public void test2()
      throws Exception {

    out.println("acting on class B first:");

    A a = new A(); B b = new B();
    a.setB(b);     b.setA(a);

    b.actionOnA();
  }
}

The output is as follows:

acting on class A first:
A : calling class B action.
B : calling class A action.
acting on class B first:
B : calling class A action.
A : calling class B action.

Well, this works, but does not seem to be the optimal solution.

?
, ?

EDIT:
.
, , Element. remove (someElement), removeMe().
, , .

+3
8

private/internal. , , , .

, /, :

public class Container
{
    public void Remove(Element e)
    {
        e.RemoveImplementation();
        RemoveImplementation();
    }

    // Not directly callable by client code, but callable
    // from Element class in the same package
    protected void RemoveImplementation()
    {
       // Mess with internals of this class here
    }
}


public class Element
{
    private Container container;

    public void Remove()
    {
       RemoveImplementation();
       container.RemoveImplementation();
    }

    // Not directly callable by client code, but callable
    // from Container class in the same package
    protected void RemoveImplementation()
    {
        // Mess with internals of this class here.
    }
}

, .

+2

, . , - ... . .

+8

. , , . , , , .

:
, , " " , remove " " . , , removeMe , .

+1

, . , ? ?

Uni " ", " ", . , ?

: .

, , ?

, .

+1

, ( , ). , ([ ]), ; , , . if false. true.

.

+1

, . , - AtomicBoolean

private final AtomicBoolean actionOnBLock = new AtomicBoolean();

public void actionOnB() {
    if (!actionOnBLock.getAndSet(true))
        try {
            b.actionOnA();
        } finally {
            actionOnBLock.set(false);
        }
}

, , . , A B, .

public class AB {
   private final A a;
   private final B b;
   public AB(A a, B b) {
     this.a = a;
     this.b = b;
   }

   public void action() {
     a.action(); // doesn't call b.
     b.action(); // doesn't call a.
   }
}
0

, , , . , . , , A B ( ), , A , A , , . .

(, C E), C C.remove(E e) E E.remove(), :

class C:
    elements = [...] // List of elements

    remove(e):
        if not elements.contains(e):
            return

        elements.remove(e)
        // Do necessary internal stuff here...
        // and finally call remove on e
        e.remove()

class E:
    container = ... // The current container of E

    remove():
        if container is none:
            return

        c = container
        container = none
        // Do necessary internal stuff here...
        // and finally call remove on c
        c.remove(this)
0

fooA() fooB() fooB(), fooA() - . , .

, ? ?

, . .

,

if not elements.contains(e):
            return

if container is none:
            return
0

Source: https://habr.com/ru/post/1709907/


All Articles